JavaScript-এ SharedArrayBuffer

এই প্রবন্ধটি JavaScript-এ SharedArrayBuffer-এর ব্যাখ্যা করে।

SharedArrayBuffer এর বুনিয়াদি, ব্যবহার করার উপায়, নির্দিষ্ট ব্যবহারক্ষেত্র এবং সুরক্ষা সংক্রান্ত বিষয়গুলির একটি বিশদ ব্যাখ্যা আমরা প্রদান করব।

YouTube Video

JavaScript-এ SharedArrayBuffer

SharedArrayBuffer হল JavaScript-এ একটি শক্তিশালী টুল যা একাধিক থ্রেডের মধ্যে মেমরি শেয়ার করতে দেয়। বিশেষত Web Workers-এর সাথে একত্রে ব্যবহারে এটি সমান্তরাল প্রসেসিং সক্ষম করে, যা গণনা-প্রধান কাজ এবং রিয়েল-টাইম ক্ষমতা প্রয়োজন এমন অ্যাপ্লিকেশনগুলির জন্য কার্যকর।

SharedArrayBuffer কী?

SharedArrayBuffer JavaScript-এ একটি মেমরি বাফার প্রদান করে যা একাধিক থ্রেডের (প্রধানত Web Workers) মধ্যে বাইনারি ডেটা ভাগ করতে দেয়। একটি সাধারণ ArrayBuffer-এ প্রধান থ্রেড এবং কর্মীদের মধ্যে ডেটা অনুলিপি করতে হয়, কিন্তু SharedArrayBuffer কোনও অনুলিপি ছাড়াই সরাসরি মেমরি শেয়ার করার অনুমতি দেয়, যার ফলে কর্মক্ষমতা উল্লেখযোগ্যভাবে বাড়ে।

বৈশিষ্ট্যসমূহ

  • শেয়ার্ড মেমরি এটি একাধিক থ্রেডকে একই মেমরি স্পেসে কাজ করার অনুমতি দেয়।
  • পারফরম্যান্স উন্নতি অনুলিপি এড়ানো যেতে পারে বলে, বড় পরিমাণ ডেটা প্রসেস করার সময় ওভারহেড কমে যায়।
  • থ্রেড সিঙ্ক্রোনাইজেশন আপনি এটিকে Atomics এর সাথে ব্যবহার করতে পারেন, যাতে মেমরি অ্যাক্সেস করার সময় সংঘর্ষ এড়াতে সিঙ্ক্রোনাইজেশন করা যায়।

প্রাথমিক ব্যবহারের উদাহরণ

 1// Create a 16-byte shared memory
 2const sharedBuffer = new SharedArrayBuffer(16);
 3
 4// Treat it as an Int32Array
 5const sharedArray = new Int32Array(sharedBuffer);
 6
 7// Set a value
 8sharedArray[0] = 42;
 9
10console.log(sharedArray[0]);  // 42

এই উদাহরণে, আমরা SharedArrayBuffer ব্যবহার করে একটি ১৬-বাইট মেমরি এলাকা তৈরি করেছি এবং সেই মেমরি এলাকাটিকে একটি Int32Array হিসাবে বিবেচনা করেছি। এই মেমরি বাফারটি একাধিক থ্রেডের মধ্যে ভাগ করা যেতে পারে।

Web Workers-এর সাথে ব্যবহার

SharedArrayBuffer-এর প্রকৃত মূল্য Web Workers-এর সাথে একত্রে ব্যবহারে প্রদর্শিত হয়। নিচের কোডটি প্রধান থ্রেড এবং একটি কর্মীর মধ্যে শেয়ার করা মেমরি ব্যবহারের একটি উদাহরণ।

প্রধান থ্রেডে

 1// Create a shared buffer
 2const sharedBuffer = new SharedArrayBuffer(16);
 3const sharedArray = new Int32Array(sharedBuffer);
 4
 5// Create a worker
 6const worker = new Worker('worker.js');
 7
 8// Pass the shared buffer to the worker
 9worker.postMessage(sharedBuffer);
10
11// Modify the memory
12// Output : Main thread: 100
13sharedArray[0] = 100;
14console.log("Main thread: ", sharedArray[0]);

কর্মীর পাশে (worker.js)

 1// worker.js
 2self.onmessage = function(event) {
 3    // Use the received shared buffer
 4    const sharedArray = new Int32Array(event.data);
 5
 6    // Read the contents of the memory
 7    // Output : Worker thread: 100
 8    console.log("Worker thread: ", sharedArray[0]);
 9
10    // Change the value
11    sharedArray[0] = 200;
12};
  • এই উদাহরণে, প্রধান থ্রেড একটি শেয়ার করা বাফার তৈরি করে এবং এটি কর্মীর কাছে পাঠায়। কর্মী এই বাফারে অ্যাক্সেস করে মান পড়তে এবং পরিবর্তন করতে পারে। এইভাবে, থ্রেডগুলির মধ্যে ডেটা কোনও অনুলিপি ছাড়াই ভাগ করা যায়।

দ্বিমুখী আপডেট নিশ্চিতকরণ

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

প্রধান থ্রেডে

 1// Create a shared buffer
 2const sharedBuffer = new SharedArrayBuffer(16);
 3const sharedArray = new Int32Array(sharedBuffer);
 4
 5// Create a worker
 6const worker = new Worker('worker.js');
 7
 8// Pass the shared buffer to the worker
 9worker.postMessage(sharedBuffer);
10
11// Set initial value
12// Output : Main thread initial: 100
13sharedArray[0] = 100;
14console.log("Main thread initial:", sharedArray[0]);
15
16// Listen for worker confirmation
17worker.onmessage = () => {
18    // Output : Main thread after worker update: 200
19    console.log("Main thread after worker update:", sharedArray[0]);
20};

কর্মীর পাশে (worker.js)

 1// worker.js
 2self.onmessage = function(event) {
 3    const sharedArray = new Int32Array(event.data);
 4
 5    // Read initial value
 6    // Output : Worker thread received: 100
 7    console.log("Worker thread received:", sharedArray[0]);
 8
 9    // Update the value
10    sharedArray[0] = 200;
11
12    // Notify main thread
13    self.postMessage("Value updated");
14};
  • এই উদাহরণে, প্রধান থ্রেড প্রথমে 100 মান লিখে, এবং ওয়ার্কার মানটি পড়ার পরে, এটি 200 এ পরিবর্তন করে। এরপর, ওয়ার্কার প্রধান থ্রেডকে জানান দেয়, এবং প্রধান থ্রেড আবার শেয়ার্ড মেমরি পড়ে আপডেটটি নিশ্চিত করে। এইভাবে, নোটিফিকেশনগুলো সংযুক্ত করে দ্বিমুখী আপডেট নিশ্চিতকরণ সম্ভব হয়।

Atomics ব্যবহার করে সমন্বয়

শেয়ারড মেমোরি ব্যবহার করার সময়, ডেটা রেস কন্ডিশন এবং অসঙ্গতিগুলো সম্পর্কে সচেতন হওয়া জরুরী। যখন একাধিক থ্রেড একই মেমোরি একসাথে অ্যাক্সেস করে, তখন সংঘর্ষ ঘটতে পারে। এটি প্রতিরোধ করার জন্য, জাভাস্ক্রিপ্ট সিঙ্ক্রোনাইজেশনের জন্য Atomics অবজেক্ট ব্যবহার করে।

উদাহরণস্বরূপ, একাধিক থ্রেড দিয়ে একটি কাউন্টার নিরাপদে বাড়ানোর জন্য, সংঘর্ষ এড়াতে আপনি Atomics ব্যবহার করতে পারেন।

1const sharedBuffer = new SharedArrayBuffer(16);
2const sharedArray = new Int32Array(sharedBuffer);
3
4// Increment the counter
5Atomics.add(sharedArray, 0, 1);
6
7console.log(Atomics.load(sharedArray, 0));  // 1

Atomics.add একটি নির্দিষ্ট ইন্ডেক্সে মান অ্যাটমিকালি বৃদ্ধি করে এবং নতুন মান রিটার্ন করে। এই অপারেশনটি অন্যান্য থ্রেডের সাথে সংঘর্ষমুক্ত থাকার নিশ্চয়তা দেয়। Atomics.load শেয়ারড মেমোরি থেকে মানগুলি নিরাপদে পড়ার জন্যও ব্যবহৃত হয়।

Atomics.wait এবং Atomics.notify ব্যবহার করে অপেক্ষা এবং নোটিফিকেশন

SharedArrayBuffer ব্যবহার করার সময় এমন পরিস্থিতি আসতে পারে যেখানে একটি ওয়ার্কারকে নির্দিষ্ট কোন শর্ত পূরণ না হওয়া পর্যন্ত অপেক্ষা করতে হয়, এবং যখন অন্য একটি ওয়ার্কার ওই শর্ত পূরণ করে, তখন তাকে অপেক্ষমাণ ওয়ার্কারকে জানান দিতে হয়। এ ধরনের ক্ষেত্রে, Atomics.wait এবং Atomics.notify খুবই উপকারী।

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

 1// Create a shared buffer (1 Int32 slot is enough for signaling)
 2const sharedBuffer = new SharedArrayBuffer(4);
 3const sharedArray = new Int32Array(sharedBuffer);
 4
 5// Create workers with names
 6const waiter = new Worker('worker.js', { name: 'waiter' });
 7const notifier = new Worker('worker.js', { name: 'notifier' });
 8
 9// Pass the shared buffer to both
10waiter.postMessage(sharedBuffer);
11notifier.postMessage(sharedBuffer);
12
13// Listen for messages
14waiter.onmessage = (event) => {
15    console.log(`[Main] Message from waiter:`, event.data);
16};
17notifier.onmessage = (event) => {
18    console.log(`[Main] Message from notifier:`, event.data);
19};
  • প্রধান থ্রেডে, একটি SharedArrayBuffer শেয়ার্ড মেমোরি হিসেবে তৈরি করা হয় এবং এটি শুধুমাত্র একটি উপাদান বিশিষ্ট Int32Array-এ রূপান্তরিত হয়। এই একক পূর্ণসংখ্যার স্লটটি ওয়ার্কারদের মধ্যে同步 করার সংকেত হিসেবে ব্যবহৃত হয়। পরবর্তীতে, দুটি ওয়ার্কার তৈরি করা হয় এবং name প্রপার্টি ব্যবহার করে প্রত্যেকটিকে একটি ভূমিকা নির্ধারণ করা হয়: waiter (অপেক্ষার ভূমিকা) এবং notifier (অবহিতকারী ভূমিকা)। শেষে, শেয়ার্ড বাফারটি উভয় ওয়ার্কারকে দেওয়া হয় এবং onmessage হ্যান্ডলার সেটআপ করা হয় যাতে প্রতিটি ওয়ার্কার থেকে প্রেরিত বার্তা গ্রহণ করা যায়।

কর্মীর পাশে (worker.js)

 1// worker.js
 2onmessage = (event) => {
 3    const sharedArray = new Int32Array(event.data);
 4
 5    if (self.name === 'waiter') {
 6        postMessage('Waiter is waiting...');
 7        // Wait until notifier signals index 0
 8        Atomics.wait(sharedArray, 0, 0);
 9        postMessage('Waiter was notified!');
10    }
11
12    if (self.name === 'notifier') {
13        postMessage('Notifier is preparing...');
14        setTimeout(() => {
15            // Notify waiter after 2 seconds
16            Atomics.store(sharedArray, 0, 1);
17            Atomics.notify(sharedArray, 0, 1);
18            postMessage('Notifier has sent the signal!');
19        }, 2000);
20    }
21};
22// Output
23// [Main] Message from waiter: Waiter is waiting...
24// [Main] Message from notifier: Notifier is preparing...
25// [Main] Message from notifier: Notifier has sent the signal!
26// [Main] Message from waiter: Waiter was notified!
  • এই উদাহরণে, waiter ওয়ার্কারটি Atomics.wait ব্যবহার করে অপেক্ষার স্থায়ীতে থাকে যতক্ষণ না ইনডেক্স 0-এর মান 0 থাকে। অন্যদিকে, যখন notifier ওয়ার্কারটি Atomics.store দিয়ে মানটি 123-এ পরিবর্তন করে এবং Atomics.notify কল করে, তখন waiter ওয়ার্কারটি আবার চালু হবে এবং হালনাগাদ মানটি পাবে। এর মাধ্যমে, থ্রেডের মধ্যে কার্যকর এবং নিরাপদ অপেক্ষা ও বিজ্ঞপ্তি সম্ভব হয়।

SharedArrayBuffer ব্যবহারের ক্ষেত্রসমূহ

SharedArrayBuffer বিশেষভাবে নিচের ব্যবহারের ক্ষেত্রে উপকারী হতে পারে:।

  • রিয়েল-টাইম প্রসেসিং এটি কম লেটেন্সি প্রয়োজন এমন অ্যাপ্লিকেশনের জন্য উপযুক্ত, যেমন অডিও ও ভিডিও প্রসেসিং অথবা গেম ইঞ্জিন, যেখানে থ্রেডগুলোর মধ্যে দ্রুত ডেটা ভাগাভাগি করার দরকার হয়।
  • সমান্তরাল প্রসেসিং একইসঙ্গে একাধিক থ্রেড দিয়ে অনেক ডেটা প্রসেস করার সময়, SharedArrayBuffer ব্যবহার করলে মেমরি কপি করা এড়ানো যায় এবং পারফরম্যান্স উন্নত হয়।
  • মেশিন লার্নিং ডেটা প্রিপ্রসেসিং ও ইনফারেন্সের মতো কাজগুলো সমান্তরালভাবে সম্পাদন করলে, আরও কার্যকরীভাবে গণনা করা সম্ভব হয়।

নিরাপত্তা বিবেচনাসমূহ

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

  • সাইট আইসোলেশন SharedArrayBuffer ব্যবহারের অনুমতি দেয় এমন সাইটসমূহ সম্পূর্ণরূপে অন্যান্য সাইট থেকে পৃথক একটি প্রসেসে চলবে।
  • ক্রস-ওরিজিন রিসোর্স পলিসি SharedArrayBuffer ব্যবহারের জন্য Cross-Origin-Opener-Policy এবং Cross-Origin-Embedder-Policy হেডারগুলি সঠিকভাবে সেট করতে হবে।

উদাহরণস্বরূপ, নিচের মত হেডার সেট করার মাধ্যমে SharedArrayBuffer ব্যবহারের সুযোগ সম্ভব হয়:।

1Cross-Origin-Opener-Policy: same-origin
2Cross-Origin-Embedder-Policy: require-corp

এটি বাইরের রিসোর্সকে বর্তমান বিষয়বস্তুর সাথে হস্তক্ষেপ থেকে রোধ করে এবং নিরাপত্তা বাড়ায়।

সারসংক্ষেপ

SharedArrayBuffer একাধিক থ্রেডের মধ্যে মেমোরি শেয়ার করার জন্য একটি অত্যন্ত শক্তিশালী টুল। এটি একটি অপরিহার্য প্রযুক্তি কর্মক্ষমতা উন্নত করার জন্য, এবং এর প্রভাব বিশেষ করে রিয়েল-টাইম প্রসেসিং এবং প্যারালাল কম্পিউটিং ক্ষেত্রে বিশেষভাবে প্রমাণিত। তবে, এটি সিকিউরিটি ঝুঁকির সাথে জড়িত, তাই সঠিক কনফিগারেশন এবং সিঙ্ক্রোনাইজেশন গুরুত্বপূর্ণ।

SharedArrayBuffer ব্যবহার করে আপনি আরও উন্নত ও উচ্চ পারফরম্যান্সের ওয়েব অ্যাপ্লিকেশন তৈরি করতে পারেন।

আপনি আমাদের ইউটিউব চ্যানেলে ভিজ্যুয়াল স্টুডিও কোড ব্যবহার করে উপরের নিবন্ধটি অনুসরণ করতে পারেন। দয়া করে ইউটিউব চ্যানেলটিও দেখুন।

YouTube Video