WebAssembly गार्बेज कलेक्शन (WasmGC) को अब Chrome में डिफ़ॉल्ट रूप से चालू कर दिया गया है

प्रोग्रामिंग भाषाएं दो तरह की होती हैं: ट्रैश इकट्ठा करने वाली प्रोग्रामिंग भाषाएं और ऐसी प्रोग्रामिंग भाषाएं जिन्हें मैन्युअल तरीके से मेमोरी मैनेजमेंट की ज़रूरत होती है. Kotlin, PHP या Java जैसे और भी उदाहरण हैं. C, C++ या रस्ट, नीचे दिए गए उदाहरण के उदाहरण हैं. आम तौर पर, हाई-लेवल प्रोग्रामिंग भाषाओं में कचरा इकट्ठा करने की एक स्टैंडर्ड सुविधा की संभावना ज़्यादा होती है. इस ब्लॉग पोस्ट में, कचरा इकट्ठा करने वाली प्रोग्रामिंग भाषाओं पर फ़ोकस किया गया है. साथ ही, यह भी बताया गया है कि इन भाषाओं को WebAssembly (Wasm) में कैसे जोड़ा जा सकता है. लेकिन कचरा इकट्ठा करने का तरीका क्या है (जिसे अक्सर जीसी कहा जाता है)?

ब्राउज़र सहायता

  • 119
  • 119
  • 120
  • x

कचरा हटाने की सुविधा

आसान शब्दों में कहें, तो कूड़ा संग्रह का मतलब ऐसी मेमोरी पर फिर से दावा करने की कोशिश है जिसे प्रोग्राम के लिए असाइन किया गया था, लेकिन अब उसका संदर्भ नहीं दिया गया है. ऐसी याद को कचरा कहा जाता है. कचरा इकट्ठा करने की सुविधा को लागू करने के लिए कई रणनीतियां हैं. इनमें से एक है रेफ़रंस की गिनती. इसका मकसद, मेमोरी में मौजूद ऑब्जेक्ट के रेफ़रंस की संख्या की गिनती करना होता है. किसी ऑब्जेक्ट के और रेफ़रंस न होने पर, उसे 'इस्तेमाल नहीं किया गया' के तौर पर मार्क किया जा सकता है. इससे उसे कचरा इकट्ठा करने के लिए तैयार किया जा सकता है. PHP का गार्बेज कलेक्टर, पहचान फ़ाइलों की गिनती करने की सुविधा का इस्तेमाल करता है. साथ ही, Xdebug एक्सटेंशन के xdebug_debug_zval() फ़ंक्शन का इस्तेमाल करके, कूड़ा इकट्ठा करने की सुविधा की मदद से उसके बारे में जानकारी पाई जा सकती है. नीचे दिए गए PHP प्रोग्राम पर विचार करें.

<?php
  $a= (string) rand();
  $c = $b = $a;
  $b = 42;
  unset($c);
  $a = null;
?>

यह प्रोग्राम, a नाम के नए वैरिएबल को किसी स्ट्रिंग को कास्ट किया गया रैंडम नंबर असाइन करता है. इसके बाद, यह b और c नाम के दो नए वैरिएबल बनाकर उन्हें a की वैल्यू असाइन करता है. इसके बाद, यह b को 42 नंबर फिर से असाइन कर देता है. इसके बाद, c को अनसेट कर देता है. आखिर में, यह a का मान null पर सेट करता है. xdebug_debug_zval() के साथ प्रोग्राम के हर चरण की जानकारी देते हुए, ट्रैश कलेक्टर का रेफ़रंस काउंटर देखा जा सकता है.

<?php
  $a= (string) rand();
  $c = $b = $a;
  xdebug_debug_zval('a');
  $b = 42;
  xdebug_debug_zval('a');
  unset($c);
  xdebug_debug_zval('a');
  $a = null;
  xdebug_debug_zval('a');
?>

ऊपर दिए गए उदाहरण में, नीचे दिए गए लॉग मिलेंगे. यहां आपको दिखेगा कि हर चरण के बाद, वैरिएबल a की वैल्यू के रेफ़रंस की संख्या कम कैसे होती है. यह कोड क्रम के हिसाब से सही होता है. (आपकी रैंडम संख्या निश्चित तौर पर अलग होगी.)

a:
(refcount=3, is_ref=0)string '419796578' (length=9)
a:
(refcount=2, is_ref=0)string '419796578' (length=9)
a:
(refcount=1, is_ref=0)string '419796578' (length=9)
a:
(refcount=0, is_ref=0)null

कचरा इकट्ठा करने में अन्य चुनौतियां भी हैं, जैसे कि साइकल का पता लगाना. हालांकि, इस लेख के लिए, पहचान फ़ाइल की संख्या को बुनियादी तौर पर समझना काफ़ी है.

प्रोग्रामिंग भाषाओं को अन्य प्रोग्रामिंग भाषाओं में लागू किया जाता है

ऐसा लग सकता है कि यह ऐप्लिकेशन के रिलीज़ होने जैसा है. हालांकि, प्रोग्रामिंग भाषाओं को अन्य प्रोग्रामिंग भाषाओं में लागू किया जाता है. उदाहरण के लिए, PHP रनटाइम को मुख्य तौर पर C में लागू किया जाता है. GitHub पर पीएचपी सोर्स कोड देखा जा सकता है. PHP का कूड़ा संग्रह कोड मुख्य रूप से zend_gc.c फ़ाइल में मौजूद होता है. ज़्यादातर डेवलपर अपने ऑपरेटिंग सिस्टम के पैकेज मैनेजर के ज़रिए PHP इंस्टॉल करेंगे. हालांकि, डेवलपर सोर्स कोड से भी PHP बना सकते हैं. उदाहरण के लिए, Linux एनवायरमेंट में ./buildconf && ./configure && make दिए गए चरणों से, Linux रनटाइम के लिए PHP बनाया जाएगा. इसका यह भी मतलब है कि PHP रनटाइम को अन्य रनटाइम के लिए कंपाइल किया जा सकता है, जैसे कि आपने सही अनुमान लगाया, Wasm.

Wasm रनटाइम में भाषाओं को पोर्ट करने के पारंपरिक तरीके

PHP से चल रहे प्लैटफ़ॉर्म पर अलग तरीके से, PHP स्क्रिप्ट को उसी बाइट कोड में इकट्ठा किया जाता है और उन्हें Zend Engine की मदद से चलाया जाता है. Zend Engine, PHP स्क्रिप्टिंग भाषा के लिए एक कंपाइलर और रनटाइम एनवायरमेंट है. इसमें Zend Virtual Machine (वीएम) शामिल है, जो Zend Compiler और Zend एक्ज़ीक्यूटिव से बना है. PHP जैसी दूसरी हाई-लेवल भाषाओं में लागू की गई C जैसे कि भाषाओं में आम तौर पर ऑप्टिमाइज़ेशन होते हैं, जो Intel या ARM जैसे खास आर्किटेक्चर को टारगेट करते हैं. साथ ही, हर आर्किटेक्चर के लिए एक अलग बैकएंड की ज़रूरत होती है. इस संदर्भ में, Wasm एक नए आर्किटेक्चर को दिखाता है. अगर वीएम में आर्किटेक्चर के हिसाब से बना कोड है, जैसे कि जस्ट-इन-टाइम (जेआईटी) या प्री-ऑफ़-टाइम (एओटी) कंपाइलेशन, तो डेवलपर नए आर्किटेक्चर के लिए JIT/AOT का बैकएंड भी लागू करता है. यह तरीका बहुत कारगर साबित होता है, क्योंकि हर नए आर्किटेक्चर के लिए अक्सर कोडबेस के मुख्य हिस्से को दोबारा इकट्ठा किया जा सकता है.

Wasm का लेवल कम होने पर भी यहां वही तरीका अपनाया जा सकता है: मुख्य वीएम कोड को उसके पार्सर, लाइब्रेरी सपोर्ट, कूड़े इकट्ठा करने की सुविधा, और Wasm के ऑप्टिमाइज़र के साथ फिर से कंपाइल करें. साथ ही, ज़रूरी होने पर Wasm के लिए JIT या AOT बैकएंड लागू करें. Wasm MVP के बाद से ऐसा करना मुमकिन है और कई मामलों में यह अच्छे से काम करता है. असल में, WordPress Playground में PHP इकट्ठा करके उसे इकट्ठा किया जाता है. इस प्रोजेक्ट के बारे में ज़्यादा जानने के लिए, WordPress Playground और WebAssembly की मदद से ब्राउज़र में मौजूद WordPress अनुभव बनाना लेख पढ़ें.

हालांकि, PHP Wasm ब्राउज़र में होस्ट भाषा की JavaScript के संदर्भ में चलता है. Chrome में, JavaScript और Wasm को V8 में चलाया जाता है. यह Google का ओपन सोर्स JavaScript इंजन है, जो ECMA-262 में बताए गए तरीके के मुताबिक ECMAScript को लागू करता है. साथ ही, V8 में पहले से ही गार्बेज कलेक्टर मौजूद है. इसका मतलब है कि जो डेवलपर, Wasm के लिए इकट्ठा की गई PHP से इकट्ठा की गई फ़ाइल का इस्तेमाल करते हैं, वे ट्रैश कलेक्टर लागू करने वाली भाषा (PHP) को उस ब्राउज़र में भेज देते हैं जिसमें पहले से ही कूड़ा इकट्ठा करने वाला टूल मौजूद है. यह उतना ही नुकसान पहुंचाने वाला है जितना लगता है. ऐसी ही स्थिति में WasmGC की अहम भूमिका होती है.

Wasm मॉड्यूल को Wasm की लीनियर मेमोरी के साथ अपना जीसी बनाने की अनुमति देने से जुड़ी दूसरी समस्या यह है कि Wasm का ट्रैश कलेक्टर और कंपाइल्ड-टू-वॉज़म लैंग्वेज के बिल्ट-ऑन कचरा कलेक्टर के बीच कोई इंटरैक्शन नहीं होता है. इससे मेमोरी लीक होने और डेटा इकट्ठा करने की कोशिश करने जैसी समस्याएं हो सकती हैं. Wasm मॉड्यूल को पहले से मौजूद जीसी फ़ॉर्मैट में फिर से इस्तेमाल करने से, इन समस्याओं से बचा जा सकता है.

WasmGC की मदद से, प्रोग्रामिंग भाषाओं को नए रनटाइम पर पोर्ट करना

WasmGC, WebAssembly कम्यूनिटी ग्रुप का एक प्रपोज़ल है. Wasm के एमवीपी को लागू करने की मौजूदा प्रोसेस में सिर्फ़ संख्याओं, यानी पूर्णांक और फ़्लोट को, लीनियर मेमोरी में ही इस्तेमाल किया जा सकता है. साथ ही, पहचान फ़ाइलों के टाइप वाले प्रस्ताव को शिप किए जाने के बाद, Wasm के अलावा बाहरी रेफ़रंस भी जोड़े जा सकते हैं. WasmGC में अब स्ट्रक्चर और अरे हीप टाइप जोड़े गए हैं. इसका मतलब है कि नॉन-लीनियर मेमोरी ऐलोकेशन के साथ काम करता है. हर WasmGC ऑब्जेक्ट का एक तय टाइप और स्ट्रक्चर होता है. इससे वीएम को अपने फ़ील्ड को ऐक्सेस करने के लिए, बेहतर कोड जनरेट करना आसान हो जाता है. साथ ही, JavaScript जैसी डाइनैमिक लैंग्वेज के डेटा को ऑप्टिमाइज़ न करने का जोखिम नहीं होता. इस प्रस्ताव से, स्ट्रक्चर्ड और अरे हीप टाइप की मदद से, WebAssembly में मैनेज की जा रही हाई-लेवल भाषाओं के लिए बेहतर सहायता मिलती है. इससे, Wasm को टारगेट करने वाले लैंग्वेज कंपाइलर को, होस्ट वीएम में ट्रैश कलेक्टर के साथ इंटिग्रेट करने की सुविधा मिलती है. आसान शब्दों में कहें, तो इसका मतलब है कि WasmGC के साथ, किसी प्रोग्रामिंग भाषा को Wasm में पोर्ट करने का मतलब है कि प्रोग्रामिंग भाषा के गार्बेज कलेक्टर को अब पोर्ट का हिस्सा बनाने की ज़रूरत नहीं है. इसके बजाय, मौजूदा कचरा इकट्ठा करने वाले टूल का इस्तेमाल किया जा सकता है.

इस सुधार का असल दुनिया पर क्या असर हुआ, इसकी पुष्टि करने के लिए, Chrome की Wasm टीम ने C, रस्ट, और Java से Fannkoch मानदंड (जो डेटा स्ट्रक्चर को काम करने के दौरान असाइन किया जाता है) का कंपाइल वर्शन तैयार किया है. कई कंपाइलर फ़्लैग के आधार पर, C और Rust बाइनरी की वैल्यू 6.1 K से 9.6 K तक हो सकती है. हालांकि, Java वर्शन का साइज़ सिर्फ़ 2.3 K ही है! C और Rust में गार्बेज कलेक्टर शामिल नहीं होते, लेकिन वे अब भी मेमोरी को मैनेज करने के लिए malloc/free को बंडल करते हैं और Java यहां छोटा होने की वजह यह है कि इसे किसी मेमोरी मैनेजमेंट कोड को बंडल करने की ज़रूरत नहीं होती. यह सिर्फ़ एक उदाहरण है, लेकिन इससे पता चलता है कि WasmGC बाइनरी के बहुत छोटे होने की संभावना है. इतना ही नहीं, साइज़ को ऑप्टिमाइज़ करने की दिशा में किए जाने वाले किसी भी अहम काम से पहले भी ऐसा ही हो रहा है.

WasmGC की पोर्ट की गई प्रोग्रामिंग भाषा को देखना

Kotlin Wasm

WasmGC की मदद से, Wasm में पोर्ट की जाने वाली शुरुआती प्रोग्रामिंग भाषाओं में से एक Kotlin है, जो Kotlin/Wasm के रूप में है. Kotlin टीम के सोर्स कोड के साथ डेमो को यहां दिए गए स्टोर पेज में दिखाया गया है.

import kotlinx.browser.document
import kotlinx.dom.appendText
import org.w3c.dom.HTMLDivElement

fun main() {
    (document.getElementById("warning") as HTMLDivElement).style.display = "none"
    document.body?.appendText("Hello, ${greet()}!")
}

fun greet() = "world"

अब आप सोच रहे होंगे कि बात क्या है, क्योंकि ऊपर दिए गए Kotlin कोड में मूल रूप से JavaScript OM API को Kotlin में बदला गया है. Compose Multiplatform के साथ इस टूल का इस्तेमाल करना ज़्यादा काम का है. इससे डेवलपर अपने Android Kotlin ऐप्लिकेशन के लिए, पहले से बनाए गए यूज़र इंटरफ़ेस (यूआई) पर काम कर सकते हैं. Kotlin/Wasm इमेज व्यूअर डेमो की मदद से इसके बारे में शुरुआती जानकारी देखें और इसके सोर्स कोड को एक्सप्लोर करें. यह भी ज़रूरी है कि इसे Kotlin टीम में बनाया जाए.

डार्ट और फ़्लटर

Google की Dart और Flutter टीम भी WasmGC के लिए सहायता तैयार कर रही है. Dart-to-Wasm के कंपाइलेशन का काम करीब-करीब पूरा हो गया है. टीम, WebAssembly में इकट्ठा किए गए Flutter वेब ऐप्लिकेशन को डिलीवर करने के लिए, टूल पर काम कर रही है. Flutter दस्तावेज़ में जाकर, इस काम की मौजूदा स्थिति के बारे में पढ़ा जा सकता है. नीचे दिया गया डेमो, Flutter WasmGC Preview है.

WasmGC के बारे में ज़्यादा जानें

इस ब्लॉग पोस्ट में अभी कोई नई जानकारी नहीं है और ज़्यादातर WasmGC के बारे में खास जानकारी दी गई है. इस सुविधा के बारे में ज़्यादा जानने के लिए, ये लिंक देखें:

स्वीकार हैं

Unsplash पर गैरी चैन की हीरो इमेज. इस लेख की समीक्षा मैथियस लिडके, एडम क्लाइन, जोशुआ बेल, एलॉन ज़ाकाई, जैकब कुमेरॉ, क्लेमेंस बैक्स, इमैनुअल ज़िगलर, और रेचल एंड्रू ने की है.