টাইপস্ক্রিপ্টে `SharedArrayBuffer`
এই নিবন্ধে টাইপস্ক্রিপ্টে SharedArrayBuffer ব্যাখ্যা করা হয়েছে।
আমরা ব্যবহারিক উদাহরণের মাধ্যমে টাইপস্ক্রিপ্টে SharedArrayBuffer ব্যাখ্যা করব।
YouTube Video
টাইপস্ক্রিপ্টে SharedArrayBuffer
SharedArrayBuffer হল একই মেমোরি স্পেস একাধিক থ্রেডের মধ্যে ভাগ করে নেওয়ার একটি প্রক্রিয়া, যেমন Web Workers এর ক্ষেত্রে। Atomics-এর সাথে একত্রিত করলে, আপনি ডেটা রেস নিয়ন্ত্রণ করতে এবং দ্রুত শেয়ার্ড মেমরি অপারেশন করতে পারবেন।
পূর্বশর্ত ও টীকা
ব্রাউজারে SharedArrayBuffer ব্যবহার করার সময়, cross-origin isolation নামে পরিচিত নিরাপত্তার শর্ত পূরণ করতে COOP এবং COEP হেডার প্রয়োজন। Node.js-এ, worker_threads ব্যবহার করে শেয়ার্ড মেমরি তুলনামূলকভাবে সহজেই পরিচালনা করা যায়।
মৌলিক ধারণা
SharedArrayBuffer একটি নির্দিষ্ট দৈর্ঘ্যের বাইটের ক্রম উপস্থাপন করে, এবং আপনি TypedArray ও অনুরূপ ভিউয়ের মাধ্যমে নম্বর পড়া ও লেখা করতে পারেন। সাধারণ পড়া/লেখা অপারেশনসমূহ সিঙ্ক্রোনাইজড নয়, তাই পারমাণবিক অপারেশন নিশ্চিত করতে Atomics API এবং সমন্বয়ের জন্য wait ও notify ব্যবস্থার ব্যবহার করুন।
সহজ কাউন্টার (ব্রাউজার সংস্করণ)
এই উদাহরণে, প্রধান থ্রেড একটি SharedArrayBuffer তৈরি করে এবং এটি একটি Web Worker-এ পাঠায়; উভয়ই একটি শেয়ার্ড কাউন্টার বৃদ্ধি করে। এটি সর্বনিম্ন প্যাটার্ন দেখায়: Atomics.add দিয়ে পারমাণবিক যোগ এবং Atomics.load দিয়ে পড়া।
main.ts (ব্রাউজার দিক)
এই উদাহরণে দেখানো হয়েছে কিভাবে প্রধান থ্রেড একটি SharedArrayBuffer তৈরি করে এবং এটি Worker-এর সাথে ভাগ করে বহু-থ্রেডেড অ্যাক্সেসের জন্য।
1// main.ts
2// Create a 4-byte (Int32) shared buffer for one counter
3const sab = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 1);
4const counter = new Int32Array(sab); // view over the buffer
5
6// Create worker and transfer the SharedArrayBuffer
7const worker = new Worker(new URL('./worker.ts', import.meta.url), { type: 'module' });
8worker.postMessage({ sab });
9
10// Increase counter in main thread every 200ms
11setInterval(() => {
12 const newVal = Atomics.add(counter, 0, 1) + 1; // Atomically increment
13 console.log('Main incremented ->', newVal);
14}, 200);
15
16// Listen for messages (optional)
17worker.onmessage = (e) => {
18 console.log('From worker:', e.data);
19};- এই কোডে, প্রধান থ্রেড
Atomics.addব্যবহার করে মানটি পারমাণবিকভাবে বাড়ায়।worker.ts-এর দিক থেকেও একইSharedArrayBufferঅ্যাক্সেস ও পরিচালনা করা যায়।
worker.ts (ব্রাউজার Worker)
এটি এমন একটি উদাহরণ যেখানে Worker একই শেয়ার্ড বাফার গ্রহণ করে এবং নিয়মিত কমায় বা পরিবর্তন করে।
1// worker.ts
2self.onmessage = (ev: MessageEvent) => {
3 const { sab } = ev.data as { sab: SharedArrayBuffer };
4 const counter = new Int32Array(sab);
5
6 // Every 350ms, atomically add 2 (demonstration)
7 setInterval(() => {
8 const newVal = Atomics.add(counter, 0, 2) + 2;
9 // Optionally notify main thread (postMessage)
10 self.postMessage(`Worker added 2 -> ${newVal}`);
11 }, 350);
12};- Worker ও
Int32Array-এর মাধ্যমে একই মেমরি পরিচালনা করে, এবংAtomics-এর জন্য রেস কন্ডিশন ছাড়াই আপডেট করা যায়।
wait/notify ব্যবহার করে সিঙ্ক্রোনাইজেশন
Atomics.wait ও Atomics.notify ব্যবহার করে, নির্দিষ্ট শর্ত পূরণ না হওয়া পর্যন্ত থ্রেড স্থগিত রাখা যায়, ফলে worker থ্রেডের মধ্যে ইভেন্ট-চালিত সিঙ্ক্রোনাইজেশন করা সম্ভব। ব্রাউজারে, সবচেয়ে নিরাপদ পদ্ধতি হল Worker-এর মধ্যে Atomics.wait ব্যবহার করা।
producer.ts (ব্রাউজার Producer Worker)
Producer ডেটা লেখে এবং notify ব্যবহার করে Consumer-কে অবহিত করে।
1// producer.ts (worker)
2self.onmessage = (ev: MessageEvent) => {
3 const { sab } = ev.data as { sab: SharedArrayBuffer };
4 const state = new Int32Array(sab); // state[0] will be 0=empty,1=filled
5
6 // produce every 500ms
7 setInterval(() => {
8 // produce: set state to 1 (filled)
9 Atomics.store(state, 0, 1);
10 Atomics.notify(state, 0, 1); // wake one waiter
11 self.postMessage('produced');
12 }, 500);
13};consumer.ts (ব্রাউজার Consumer Worker)
Consumer Atomics.wait দিয়ে অপেক্ষা করে এবং Producer-এর নোটিফিকেশনে প্রসেসিং পুনরায় শুরু করে।
1// consumer.ts (worker)
2self.onmessage = (ev: MessageEvent) => {
3 const { sab } = ev.data as { sab: SharedArrayBuffer };
4 const state = new Int32Array(sab);
5
6 // consumer loop
7 (async function consumeLoop() {
8 while (true) {
9 // if state is 0 => wait until notified (value changes)
10 while (Atomics.load(state, 0) === 0) {
11 // Blocks this worker until notified or timeout
12 Atomics.wait(state, 0, 0);
13 }
14 // consume (reset to 0)
15 // (processing simulated)
16 // read data from another shared buffer in real scenarios
17 Atomics.store(state, 0, 0);
18 // continue loop
19 self.postMessage('consumed');
20 }
21 })();
22};- এই প্যাটার্নে, Producer
Atomics.notifyএর মাধ্যমে Consumer-কে জানায়, এবং Consumer কার্যকরভাবেAtomics.waitব্যবহার করে অপেক্ষা করে। ব্রাউজারে প্রধান থ্রেডেAtomics.waitকল করা যায় না। UI ফ্রিজ হওয়া রোধ করতে,Atomics.waitকেবলমাত্র Worker-এর ভেতরেই ব্যবহারের জন্য সীমিত।
Node.js (worker_threads) দিয়ে ব্যবহারিক উদাহরণ
Node.js এনভায়রনমেন্টে, আপনি worker_threads ব্যবহার করে SharedArrayBuffer এর কার্যকারিতা পরিচালনা করতে পারেন। নিচে Node.js এর জন্য টাইপড টাইপস্ক্রিপ্ট নমুনা দেওয়া হয়েছে।
main-node.ts
প্রধান থ্রেড বাফার তৈরি করে এবং Worker-এ প্রেরণ করে।
1// main-node.ts
2import { Worker } from 'worker_threads';
3import path from 'path';
4
5// Create SharedArrayBuffer for one 32-bit integer
6const sab = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT);
7const counter = new Int32Array(sab);
8
9// Spawn worker and pass sab via workerData
10const worker = new Worker(path.resolve(__dirname, 'worker-node.js'), {
11 workerData: { sab }
12});
13
14// Log messages from worker
15worker.on('message', (msg) => console.log('Worker:', msg));
16
17// Increment in main thread periodically
18setInterval(() => {
19 const val = Atomics.add(counter, 0, 1) + 1;
20 console.log('Main increment ->', val);
21}, 300);worker-node.ts
এই উদাহরণে Worker দিক থেকে worker_threads-এর parentPort ও workerData ব্যবহার করা হয়েছে।
1// worker-node.ts
2import { parentPort, workerData } from 'worker_threads';
3
4const sab = workerData.sab as SharedArrayBuffer;
5const counter = new Int32Array(sab);
6
7// Periodically add 5
8setInterval(() => {
9 const val = Atomics.add(counter, 0, 5) + 5;
10 parentPort?.postMessage(`Added 5 -> ${val}`);
11}, 700);- Node.js এ, ব্রাউজারের মতো COOP বা COEP সীমাবদ্ধতা নেই, তাই শুধুমাত্র
worker_threadsব্যবহার করেই শেয়ার্ড মেমরি সহজেই পরিচালনা করা যায়। টাইপস্ক্রিপ্ট ব্যবহার করার সময়, আপনি CommonJS না ESM সেটিংস দিয়ে বিল্ড করছেন কিনা তা লক্ষ্য রাখুন।
টাইপস্ক্রিপ্ট টাইপিং নির্দেশিকা
SharedArrayBuffer ও Atomics স্ট্যান্ডার্ড DOM ও লাইব্রেরি টাইপ ডেফিনিশনে রয়েছে, তাই সরাসরি TypeScript-এ ব্যবহার করতে পারেন। Workers-এর সাথে বার্তা আদান-প্রদানের সময়, ইন্টারফেস নির্ধারণ ও টাইপ স্পষ্টভাবে উল্লেখ করা নিরাপদ।
1// Example: typed message
2type WorkerMessage = { type: 'init'; sab: SharedArrayBuffer } | { type: 'ping' };- টাইপ স্পষ্টভাবে নির্ধারণ করলে
postMessageওonmessageহ্যান্ডলিং আরও নিরাপদ হয় এবং টাইপ চেকিং সক্ষম হয়।
ব্যবহারিক ব্যবহারক্ষেত্র
SharedArrayBuffer সবসময় প্রয়োজন হয় না, তবে যেখানে শেয়ার্ড মেমোরির গতি-সম্পর্কিত সুবিধা দরকার হয়, সেই পরিস্থিতিতে এটি অত্যন্ত কার্যকরী। এটি কোন কোন পরিস্থিতিতে কার্যকরী তা বোঝা সঠিক প্রযুক্তি নির্বাচনে সহায়তা করে।
- এটি দ্রুত শেয়ার্ড বাফার দরকার এমন নিম্ন-লেটেন্সি প্রসেসিং-এর জন্য উপযুক্ত এবং বাস্তব-সময়ে অডিও/ভিডিও প্রসেসিং বা গেম ফিজিক্সে ব্যবহার করা যায়।
- সহজ ডেটা আদান-প্রদান বা বড় ডেটা স্থানান্তরের জন্য
Transferable ArrayBufferবাpostMessageহয়তোSharedArrayBuffer-এর চেয়ে সহজভাবে ব্যবহার করা যায়।
সীমাবদ্ধতা ও নিরাপত্তা
ব্রাউজারে SharedArrayBuffer ব্যবহার করতে, cross-origin isolation প্রয়োজন: COOP-কে same-origin-allow-popups এবং COEP-কে require-corp সেট করুন। এই শর্তাদি পূরণ না হলে SharedArrayBuffer নিষ্ক্রিয় থাকবে।
কর্মক্ষমতা ও ডিবাগিং টিপস
পারমাণবিক অপারেশন (Atomics) দ্রুত, তবে বারবার অপেক্ষা ও অতিরিক্ত সিঙ্ক্রোনাইজেশন লেটেন্সি বাড়াতে পারে।
শেয়ার্ড মেমরি নিরাপদে ও দক্ষতার সাথে পরিচালনার জন্য নিচের বিষয়গুলি অবশ্যই দেখা উচিত।
Int32Array-এর মতো ভিউগুলি যথাযথ বাইট অ্যালাইনমেন্টে পরিচালনা করতে হবে।- একই শেয়ার্ড বাফারের কোন ইনডেক্স কোন প্রসেস ব্যবহার করছে তা স্পষ্ট রাখুন, এবং কোডে ধারাবাহিক নিয়ম মানুন।
- যদি আপনি
SharedArrayBuffer-কে সাধারণArrayBuffer-এর মতো ব্যবহার করেন, তাহলে ডেটা রেস হবে। একই ইনডেক্সে একাধিক থ্রেড থেকেAtomicsছাড়া লেখা বিপজ্জনক।
সারসংক্ষেপ
SharedArrayBuffer ও Atomics সঠিকভাবে ব্যবহারের মাধ্যমে, TypeScript-এও নিরাপদ ও দ্রুত শেয়ার্ড মেমরি অপারেশন সম্ভব। কাউন্টার বা সংকেতের মতো সহজ সিঙ্ক্রোনাইজেশন দিয়ে শুরু করা সহজবোধ্য, এবং সঠিক সিঙ্ক্রোনাইজেশন ও ইনডেক্স যথাযথভাবে পরিচালনা করলে, আপনি নিম্ন-লেটেন্সি পরিস্থিতিতেও কার্যকর হতে পারবেন।
আপনি আমাদের ইউটিউব চ্যানেলে ভিজ্যুয়াল স্টুডিও কোড ব্যবহার করে উপরের নিবন্ধটি অনুসরণ করতে পারেন। দয়া করে ইউটিউব চ্যানেলটিও দেখুন।