ट्रांसफ़र किए जा सकने वाले ऑब्जेक्ट - बहुत तेज़ी से चार्ज होते हैं

Chrome 13 में, स्ट्रक्चर्ड क्लोनिंग नाम के एल्गोरिदम का इस्तेमाल करके, वेब वर्कर्स को ArrayBuffer भेजने/उनसे पाने की सुविधा जोड़ी गई थी. इससे postMessage() API, सिर्फ़ स्ट्रिंग ही नहीं, बल्कि File, Blob, ArrayBuffer, और JSON ऑब्जेक्ट जैसे जटिल टाइप के मैसेज भी स्वीकार कर सकता था. Firefox के नए वर्शन में भी स्ट्रक्चर्ड क्लोनिंग की सुविधा काम करती है.

ज़्यादा तेज़ बेहतर है

स्ट्रक्चर्ड क्लोनिंग की सुविधा काफ़ी अच्छी है, लेकिन यह अब भी कॉपी करने की प्रोसेस है. किसी वर्कर्स को 32 एमबी का ArrayBuffer पास करने में सैकड़ों मिलीसेकंड लग सकते हैं. ब्राउज़र के नए वर्शन में, मैसेज पास करने की परफ़ॉर्मेंस में काफ़ी सुधार किया गया है. इसे ट्रांसफ़र किए जा सकने वाले ऑब्जेक्ट कहा जाता है.

ट्रांसफ़र किए जा सकने वाले ऑब्जेक्ट की मदद से, डेटा को एक कॉन्टेक्स्ट से दूसरे कॉन्टेक्स्ट में ट्रांसफ़र किया जाता है. यह ज़ीरो-कॉपी है, जिससे किसी वर्कर्स को डेटा भेजने की परफ़ॉर्मेंस काफ़ी बेहतर होती है. अगर आप C/C++ प्रोग्रामर हैं, तो इसे पास-बाय-रेफ़रंस के तौर पर देखें. हालांकि, पास-बाय-रेफ़रंस के उलट, नए संदर्भ में ट्रांसफ़र करने के बाद, कॉलिंग कॉन्टेक्स्ट का 'वर्शन' उपलब्ध नहीं होता. उदाहरण के लिए, किसी ArrayBuffer को अपने मुख्य ऐप्लिकेशन से Worker में ट्रांसफ़र करने पर, ओरिजनल ArrayBuffer मिट जाता है और उसे फिर से इस्तेमाल नहीं किया जा सकता. इसके कॉन्टेंट को वर्कर कॉन्टेक्स्ट में ट्रांसफ़र किया जाता है.

ट्रांसफ़र किए जा सकने वाले आइटम के साथ खेलने के लिए, postMessage() का एक नया वर्शन उपलब्ध है. इसमें ट्रांसफ़र किए जा सकने वाले ऑब्जेक्ट काम करते हैं:

worker.postMessage(arrayBuffer, [transferableList]);
window.postMessage(arrayBuffer, targetOrigin, [transferableList]);

वर्कर्स केस के लिए, पहला आर्ग्युमेंट ArrayBuffer मैसेज है. दूसरा आर्ग्युमेंट, उन आइटम की सूची है जिन्हें ट्रांसफ़र करना है. इस उदाहरण में, आपको ट्रांसफ़र की जा सकने वाली सूची में arrayBuffer की जानकारी देनी होगी.

बेंचमार्क डेमो

ट्रांसफ़र किए जा सकने वाले आइटम की परफ़ॉर्मेंस में हुई बढ़ोतरी देखने के लिए, मैंने एक डेमो बनाया है.

डेमो में, postMessage() का इस्तेमाल करके किसी वर्कर को 32 एमबी का ArrayBuffer भेजा जाता है और उसे वापस पाया जाता है. अगर आपका ब्राउज़र, ट्रांसफ़र किए जा सकने वाले डेटा के साथ काम नहीं करता है, तो सैंपल को स्ट्रक्चर्ड क्लोनिंग की मदद से बनाया जाता है. अलग-अलग ब्राउज़र में औसतन पांच रन मिले. मुझे यह जानकारी मिली:

स्ट्रक्चर्ड क्लोनिंग बनाम ट्रांसफ़र किए जा सकने वाले ऑब्जेक्ट की तुलना करने वाला चार्ट

MacBook Pro/10.6.8/2.53 GHz/Intel Core 2 Duo पर, स्ट्रक्चर्ड क्लोनिंग का इस्तेमाल करके FF सबसे तेज़ था. किसी वर्कर को 32 एमबी का ArrayBuffer भेजने और उसे मुख्य थ्रेड (आरआरटी - राउंड ट्रिप टाइम) पर वापस पोस्ट करने में औसतन 302 मिलीसेकंड लगे. ट्रांसफ़र किए जा सकने वाले डेटा के साथ तुलना करने पर, उसी टेस्ट को पूरा होने में 6.6 मिलीसेकंड लगे. यह परफ़ॉर्मेंस में काफ़ी बढ़ोतरी है!

इस तरह की स्पीड से, बड़े WebGL टेक्सचर/मेश को आसानी से वर्कर्स और मुख्य ऐप्लिकेशन के बीच पास किया जा सकता है.

सुविधा का पता लगाना

इस सुविधा का पता लगाना थोड़ा मुश्किल है. हमारा सुझाव है कि आप अपने कर्मचारी को एक छोटा ArrayBuffer भेजें. अगर बफ़र को ट्रांसफ़र किया जाता है और कॉपी नहीं किया जाता है, तो उसका .byteLength 0 हो जाएगा:

var ab = new ArrayBuffer(1);
worker.postMessage(ab, [ab]);
if (ab.byteLength) {
    alert('Transferables are not supported in your browser!');
} else {
    // Transferables are supported.
}

सहायता: फ़िलहाल, यह सुविधा Chrome 17 और उसके बाद के वर्शन, Firefox, Opera, Safari, और IE10 और उसके बाद के वर्शन पर काम करती है

अपडेट किया गया (13-12-2011): webkitPostMessage() हस्ताक्षर, विंडो और वर्कर्स के लिए अलग-अलग होता है. इसे दिखाने के लिए कोड स्निपेट. अपडेट किया गया (03-11-2016): वेंडर प्रीफ़िक्स हटाए गए और कोड स्निपेट अपडेट किए गए