जावास्क्रिप्ट में SharedArrayBuffer

जावास्क्रिप्ट में SharedArrayBuffer

यह लेख जावास्क्रिप्ट में SharedArrayBuffer को समझाता है।

SharedArrayBuffer की बुनियादी बातों, इसे कैसे उपयोग करें, विशेष उपयोग के मामलों और सुरक्षा विचारों की विस्तृत व्याख्या प्रदान करेंगे।

YouTube Video

जावास्क्रिप्ट में SharedArrayBuffer

SharedArrayBuffer जावास्क्रिप्ट में मेमोरी को कई थ्रेड्स के बीच साझा करने के लिए एक शक्तिशाली उपकरण है। विशेष रूप से वेब वर्कर्स के साथ मिलाकर, यह समानांतर प्रोसेसिंग को सक्षम बनाता है, जिससे यह गणना-गहन कार्यों और वास्तविक समय क्षमताओं की आवश्यकता वाली ऐप्लिकेशन के लिए प्रभावी बन जाता है।

SharedArrayBuffer क्या है?

SharedArrayBuffer जावास्क्रिप्ट में एक मेमोरी बफ़र प्रदान करता है जो बाइनरी डेटा को कई थ्रेड्स (मुख्य रूप से वेब वर्कर्स) के बीच साझा करने की अनुमति देता है। एक नियमित 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 का उपयोग करके 16-बाइट की मेमोरी क्षेत्र बनाते हैं और उस मेमोरी क्षेत्र को Int32Array के रूप में मानते हैं। यह मेमोरी बफ़र कई थ्रेड्स के बीच साझा किया जा सकता है।

वेब वर्कर्स के साथ उपयोग करना

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// 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!
  • इस उदाहरण में, जब तक इंडेक्स 0 पर मान 0 है, waiter वर्कर Atomics.wait का उपयोग करते हुए प्रतीक्षारत स्थिति में रहता है। वहीं दूसरी ओर, जब 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 चैनल पर Visual Studio Code का उपयोग करके ऊपर दिए गए लेख के साथ आगे बढ़ सकते हैं। कृपया YouTube चैनल को भी देखें।

YouTube Video