mimalloc এবং WasmFS সহ মাল্টিথ্রেডেড ওয়েব অ্যাসেম্বলি অ্যাপ্লিকেশনগুলিকে স্কেলিং করা

আলোন জাকাই
Alon Zakai

প্রকাশিত: 30 জানুয়ারী, 2025

ওয়েবে অনেক WebAssembly অ্যাপ্লিকেশন মাল্টিথ্রেডিং থেকে উপকৃত হয়, একইভাবে নেটিভ অ্যাপ্লিকেশনগুলির মতো। একাধিক থ্রেড সমান্তরালে আরও কাজ করতে দেয় এবং লেটেন্সি সমস্যা এড়াতে প্রধান থ্রেড থেকে ভারী কাজ সরিয়ে দেয়। সম্প্রতি অবধি, কিছু সাধারণ ব্যথার পয়েন্ট ছিল যা এই ধরনের মাল্টিথ্রেডেড অ্যাপ্লিকেশনগুলির সাথে ঘটতে পারে, বরাদ্দ এবং I/O সম্পর্কিত। ভাগ্যক্রমে, এমস্ক্রিপ্টেনের সাম্প্রতিক বৈশিষ্ট্যগুলি সেই সমস্যাগুলির সাথে অনেক সাহায্য করতে পারে। এই নির্দেশিকাটি দেখায় যে কীভাবে এই বৈশিষ্ট্যগুলি কিছু ক্ষেত্রে 10 গুণ বা তার বেশি গতির উন্নতি ঘটাতে পারে।

স্কেলিং

নিম্নলিখিত গ্রাফটি একটি বিশুদ্ধ গণিত কাজের চাপে দক্ষ মাল্টিথ্রেডেড স্কেলিং দেখায় ( আমরা এই নিবন্ধে যে বেঞ্চমার্কটি ব্যবহার করব তা থেকে):

ম্যাথ স্কেলিং শিরোনামের একটি লাইন চার্ট কোরের সংখ্যা (এক্স-অক্ষ) এবং মিলিসেকেন্ডে সঞ্চালনের সময়ের মধ্যে সম্পর্ক দেখায় (y-অক্ষ, লেবেলযুক্ত

এটি বিশুদ্ধ গণনা পরিমাপ করে, এমন কিছু যা প্রতিটি সিপিইউ কোর নিজেরাই করতে পারে, তাই আরও কোরের সাথে কর্মক্ষমতা উন্নত হয়। দ্রুত পারফরম্যান্সের এই ধরনের একটি অবরোহী লাইন ঠিক কী ভালো স্কেলিং দেখায়। এবং এটি দেখায় যে ওয়েব প্ল্যাটফর্মটি মাল্টিথ্রেডেড নেটিভ কোড খুব ভালভাবে চালাতে পারে, সমান্তরালতার ভিত্তি হিসাবে ওয়েব কর্মীদের ব্যবহার করে, সত্যিকারের নেটিভ কোডের পরিবর্তে Wasm ব্যবহার করে এবং অন্যান্য বিবরণ যা কম অনুকূল মনে হতে পারে।

গাদা ব্যবস্থাপনা: malloc / free

malloc এবং free হল সমস্ত লিনিয়ার-মেমরি ল্যাঙ্গুয়েজ (উদাহরণস্বরূপ, C, C++, Rust, এবং Zig) সমস্ত মেমরি পরিচালনা করার জন্য যা সম্পূর্ণরূপে স্থির নয় বা স্ট্যাকের উপর নির্ভর করে। Emscripten ডিফল্টরূপে dlmalloc ব্যবহার করে, যা একটি কম্প্যাক্ট কিন্তু কার্যকরী বাস্তবায়ন (এটি emmalloc সমর্থন করে, যা কিছু ক্ষেত্রে আরও কমপ্যাক্ট কিন্তু ধীর)। যাইহোক, dlmalloc এর মাল্টিথ্রেড কর্মক্ষমতা সীমিত কারণ এটি প্রতিটি malloc / free এ একটি লক লাগে (কারণ একটি একক বিশ্ব বরাদ্দকারী আছে)। অতএব, আপনি যদি একবারে অনেক থ্রেডে অনেকগুলি বরাদ্দ রাখেন তবে আপনি বিতর্ক এবং ধীরগতির মধ্যে পড়তে পারেন। আপনি যখন একটি অবিশ্বাস্যভাবে malloc -heavy বেঞ্চমার্ক চালান তখন কী ঘটে তা এখানে:

dlmalloc স্কেলিং শিরোনামের একটি লাইন চার্ট মিলিসেকেন্ডে কোরের সংখ্যা (x-অক্ষ) এবং সঞ্চালন সময়ের মধ্যে সম্পর্ক দেখায় (y-অক্ষ, কম লেবেল করা ভাল)। প্রবণতাটি ইঙ্গিত করে যে কোরের সংখ্যা বৃদ্ধির ফলে উচ্চতর এক্সিকিউশন টাইম হয়, 1 থেকে 4 কোরের স্থির রৈখিক বৃদ্ধির সাথে।

শুধুমাত্র আরো কোর দিয়ে কর্মক্ষমতা উন্নত হয় না, কিন্তু এটি খারাপ থেকে খারাপ হয়ে যায়, কারণ প্রতিটি থ্রেড malloc লকের জন্য দীর্ঘ সময়ের জন্য অপেক্ষা করে। এটি সম্ভব সবচেয়ে খারাপ ক্ষেত্রে, কিন্তু পর্যাপ্ত বরাদ্দ থাকলে বাস্তব কাজের চাপে এটি ঘটতে পারে।

mimalloc

dlmalloc এর মাল্টিথ্রেড-অপ্টিমাইজ করা সংস্করণ বিদ্যমান, যেমন ptmalloc3 , যা প্রতি থ্রেডে একটি পৃথক বরাদ্দকারী উদাহরণ প্রয়োগ করে, বিতর্ক এড়িয়ে যায়। মাল্টিথ্রেডিং অপ্টিমাইজেশান সহ আরও বেশ কিছু বরাদ্দকারী বিদ্যমান, যেমন jemalloc এবং tcmalloc . Emscripten সাম্প্রতিক mimalloc প্রজেক্টের উপর ফোকাস করার সিদ্ধান্ত নিয়েছে, যা খুব ভালো বহনযোগ্যতা এবং কর্মক্ষমতা সহ মাইক্রোসফ্ট থেকে একটি সুন্দরভাবে ডিজাইন করা বরাদ্দকারী। নিম্নলিখিত হিসাবে এটি ব্যবহার করুন:

emcc -sMALLOC=mimalloc

এখানে mimalloc ব্যবহার করে malloc বেঞ্চমার্কের ফলাফল রয়েছে:

mimalloc স্কেলিং শিরোনামের একটি লাইন চার্ট কোরের সংখ্যা (x-অক্ষ) এবং মিলিসেকেন্ডে সঞ্চালনের সময়ের মধ্যে সম্পর্ক দেখায় (y-অক্ষ, কম লেবেল করা ভাল)। প্রবণতাটি ইঙ্গিত করে যে কোরের সংখ্যা বৃদ্ধি কার্যকর করার সময়কে হ্রাস করে, 1 থেকে 2 কোর থেকে একটি খাড়া ড্রপ এবং 2 থেকে 4 কোর থেকে আরও ধীরে ধীরে হ্রাস পায়।

নিখুঁত! এখন কার্যক্ষমতা স্কেল দক্ষতার সাথে, প্রতিটি কোরের সাথে দ্রুত এবং দ্রুততর হচ্ছে।

আপনি যদি শেষ দুটি গ্রাফে একক -কোর পারফরম্যান্সের ডেটা মনোযোগ সহকারে দেখেন, আপনি দেখতে পাবেন যে dlmalloc 2660 ms এবং mimalloc মাত্র 1466 নিয়েছে, যা প্রায় 2 বার গতির উন্নতি৷ এটি দেখায় যে এমনকি একটি একক-থ্রেডেড অ্যাপ্লিকেশনেও আপনি mimalloc এর আরও পরিশীলিত অপ্টিমাইজেশান থেকে সুবিধাগুলি দেখতে পারেন, যদিও মনে রাখবেন যে এটি কোড আকার এবং মেমরি ব্যবহারের খরচে আসে (যে কারণে, dlmalloc ডিফল্ট থাকে)।

ফাইল এবং I/O

অনেক অ্যাপ্লিকেশন বিভিন্ন কারণে ফাইল ব্যবহার করতে হবে. উদাহরণস্বরূপ, একটি গেমের স্তরগুলি লোড করতে, বা একটি চিত্র সম্পাদকের ফন্টগুলি৷ এমনকি printf মতো একটি অপারেশনও হুডের নিচে ফাইল সিস্টেম ব্যবহার করে, কারণ এটি stdout এ ডেটা লিখে প্রিন্ট করে।

একক-থ্রেডেড অ্যাপ্লিকেশনগুলিতে, এটি সাধারণত একটি সমস্যা নয়, এবং Emscripten স্বয়ংক্রিয়ভাবে সম্পূর্ণ ফাইল সিস্টেম সমর্থনে লিঙ্ক করা এড়াবে যদি আপনার প্রয়োজন হয় printf । যাইহোক, যদি আপনি ফাইল ব্যবহার করেন, তাহলে মাল্টিথ্রেডেড ফাইল সিস্টেম অ্যাক্সেস করা কঠিন কারণ ফাইল অ্যাক্সেস থ্রেডগুলির মধ্যে সিঙ্ক্রোনাইজ করা আবশ্যক। Emscripten-এ মূল ফাইল সিস্টেম বাস্তবায়ন, যাকে "JS FS" বলা হয় কারণ এটি জাভাস্ক্রিপ্টে প্রয়োগ করা হয়েছিল, শুধুমাত্র মূল থ্রেডে ফাইল সিস্টেম বাস্তবায়নের সহজ মডেল ব্যবহার করা হয়েছিল। যখনই অন্য থ্রেড একটি ফাইল অ্যাক্সেস করতে চায়, এটি প্রধান থ্রেডে একটি অনুরোধ প্রক্সি করে। এর মানে হল যে অন্য থ্রেডগুলি ক্রস-থ্রেড অনুরোধে ব্লক করে, যা প্রধান থ্রেড শেষ পর্যন্ত পরিচালনা করে।

এই সাধারণ মডেলটি সর্বোত্তম যদি শুধুমাত্র প্রধান থ্রেড ফাইলগুলি অ্যাক্সেস করে, যা একটি সাধারণ প্যাটার্ন। যাইহোক, যদি অন্য থ্রেডগুলি পড়তে এবং লিখতে পারে, তাহলে সমস্যাগুলি ঘটবে। প্রথমত, মূল থ্রেডটি অন্যান্য থ্রেডের জন্য কাজ করে যা ব্যবহারকারীর দৃশ্যমান লেটেন্সি সৃষ্টি করে। তারপরে, ব্যাকগ্রাউন্ড থ্রেডগুলি তাদের প্রয়োজনীয় কাজ করার জন্য প্রধান থ্রেড বিনামূল্যে হওয়ার জন্য অপেক্ষা করে, তাই জিনিসগুলি ধীর হয়ে যায় (অথবা, আরও খারাপ, যদি মূল থ্রেডটি বর্তমানে সেই কর্মী থ্রেডে অপেক্ষা করে থাকে তবে আপনি একটি অচলাবস্থায় শেষ হতে পারেন)।

WasmFS

এই সমস্যাটি সমাধান করার জন্য, Emscripten এর একটি নতুন ফাইল সিস্টেম বাস্তবায়ন রয়েছে, WasmFS । WasmFS C++ এ লেখা এবং Wasm-এ কম্পাইল করা হয়েছে, জাভাস্ক্রিপ্টে থাকা আসল ফাইল সিস্টেমের বিপরীতে। WasmFS ন্যূনতম ওভারহেড সহ একাধিক থ্রেড থেকে ফাইল সিস্টেম অ্যাক্সেস সমর্থন করে, ফাইলগুলিকে Wasm লিনিয়ার মেমরিতে সংরক্ষণ করে, যা সমস্ত থ্রেডের মধ্যে ভাগ করা হয়। সমস্ত থ্রেড এখন সমান কর্মক্ষমতা সহ ফাইল I/O করতে পারে এবং প্রায়শই তারা একে অপরকে ব্লক করা এড়াতে পারে।

একটি সাধারণ ফাইল সিস্টেম বেঞ্চমার্ক পুরানো JS FS এর তুলনায় WasmFS এর বিশাল সুবিধা দেখায়।

ফাইল সিস্টেম পারফরম্যান্স শিরোনামের একটি বার চার্ট JS FS এবং WasmFS-এর জন্য মিলিসেকেন্ডে এক্সিকিউশন টাইম তুলনা করে (y-অক্ষ, কম লেবেল করা ভাল) দুটি বিভাগে: প্রধান থ্রেড এবং pthread (x-অক্ষ)। JS FS pthread ক্ষেত্রে উল্লেখযোগ্যভাবে বেশি সময় নেয়, যখন WasmFS উভয় ক্ষেত্রেই ধারাবাহিকভাবে কম থাকে।

এটি সরাসরি মূল থ্রেডে চলমান ফাইল সিস্টেম কোডকে একটি একক থ্রেডে চালানোর সাথে তুলনা করে। পুরানো জেএস এফএস-এ, প্রতিটি ফাইল সিস্টেম অপারেশনকে প্রধান থ্রেডের সাথে প্রক্সি করা আবশ্যক, যা এটিকে একটি থ্রেডে ধীর গতির একটি ক্রম ধরে করে! কারণ শুধু কিছু বাইট পড়া/লেখার পরিবর্তে, JS FS ক্রস-থ্রেড কমিউনিকেশন করে, যার মধ্যে লক, একটি সারি এবং অপেক্ষা জড়িত। বিপরীতে, WasmFS সমানভাবে যেকোনো থ্রেড থেকে ফাইল অ্যাক্সেস করতে পারে, এবং তাই চার্ট দেখায় যে মূল থ্রেড এবং একটি pthread এর মধ্যে কার্যত কোন পার্থক্য নেই। ফলস্বরূপ, WasmFS একটি pthread এ থাকাকালীন JS FS থেকে 32 গুণ দ্রুত।

উল্লেখ্য যে প্রধান থ্রেডে একটি পার্থক্য রয়েছে যেখানে WasmFS 2 গুণ দ্রুত। কারণ জেএস এফএস প্রতিটি ফাইল সিস্টেম অপারেশনের জন্য জাভাস্ক্রিপ্টকে কল করে, যা WasmFS এড়িয়ে যায়। WasmFS শুধুমাত্র প্রয়োজন হলে JavaScript ব্যবহার করে (উদাহরণস্বরূপ, একটি ওয়েব API ব্যবহার করার জন্য), যা Wasm-এ বেশিরভাগ WasmFS ফাইল ছেড়ে যায়। এছাড়াও, এমনকি যখন JavaScript প্রয়োজন হয়, WasmFS মূল থ্রেডের পরিবর্তে একটি সহায়ক থ্রেড ব্যবহার করতে পারে, যাতে ব্যবহারকারী-দৃশ্যমান লেটেন্সি এড়াতে পারে। এই কারণে আপনি WasmFS ব্যবহার করে গতির উন্নতি দেখতে পারেন যদিও আপনার অ্যাপ্লিকেশন মাল্টিথ্রেডেড না হয় (বা যদি এটি মাল্টিথ্রেডেড হয় তবে শুধুমাত্র মূল থ্রেডে ফাইল ব্যবহার করে)।

নিম্নলিখিত হিসাবে WasmFS ব্যবহার করুন:

emcc -sWASMFS

WasmFS উৎপাদনে ব্যবহৃত হয় এবং স্থিতিশীল বলে বিবেচিত হয়, তবে এটি এখনও পুরানো JS FS-এর সমস্ত বৈশিষ্ট্য সমর্থন করে না। অন্যদিকে, এতে মূল প্রাইভেট ফাইল সিস্টেমের জন্য সমর্থনের মতো কিছু গুরুত্বপূর্ণ নতুন বৈশিষ্ট্য অন্তর্ভুক্ত রয়েছে (OPFS, যা ক্রমাগত স্টোরেজের জন্য অত্যন্ত সুপারিশ করা হয়)। যদি না আপনার এমন একটি বৈশিষ্ট্যের প্রয়োজন হয় যা এখনও পোর্ট করা হয়নি, Emscripten টিম WasmFS ব্যবহার করার পরামর্শ দেয়।

উপসংহার

আপনার যদি একটি মাল্টিথ্রেডেড অ্যাপ্লিকেশন থাকে যা প্রচুর বরাদ্দ করে বা ফাইল ব্যবহার করে, তাহলে আপনি WasmFS এবং/অথবা mimalloc ব্যবহার করে অনেক উপকৃত হতে পারেন। এই পোস্টে বর্ণিত পতাকাগুলির সাথে পুনরায় কম্পাইল করে একটি Emscripten প্রকল্পে চেষ্টা করা উভয়ই সহজ।

আপনি যদি থ্রেডগুলি ব্যবহার না করেন তবে আপনি সেই বৈশিষ্ট্যগুলিও চেষ্টা করতে চাইতে পারেন: যেমনটি আগে উল্লেখ করা হয়েছে, আরও আধুনিক বাস্তবায়নগুলি অপ্টিমাইজেশনের সাথে আসে যা কিছু ক্ষেত্রে একক কোরেও লক্ষণীয়।