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

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

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

  • Chrome: 119. अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है
  • एज: 119. अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है
  • Firefox: 120. अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है
  • Safari: समर्थित नहीं. अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है

कचरा इकट्ठा करना

आसान शब्दों में कहें, तो गै़रबेज इकट्ठा करने का आइडिया, उस मेमोरी को वापस पाने की कोशिश है जिसे प्रोग्राम से असाइन किया गया था. हालांकि, अब इसका इस्तेमाल नहीं किया जाता. ऐसी मेमोरी को गै़रबेज कहा जाता है. कचरा इकट्ठा करने की प्रक्रिया को लागू करने के लिए कई रणनीतियां हैं. इनमें से एक पहचान फ़ाइलों की गिनती करना है. इसका मकसद, मेमोरी में मौजूद ऑब्जेक्ट के रेफ़रंस की संख्या की गिनती करना है. जब किसी ऑब्जेक्ट के लिए और रेफ़रंस न हों, तो उसे 'इस्तेमाल नहीं किया गया' के तौर पर मार्क किया जा सकता है. इससे, वह गै़रबेज कलेक्शन के लिए तैयार होता है. 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 सोर्स कोड देखा जा सकता है. 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 (VM) शामिल है, जो Zend कंपाइलर और Zend एक्ज़ीक्यूटिव से मिलकर बनती है. PHP जैसी अन्य हाई-लेवल भाषाओं में लागू की जाने वाली भाषाओं में, आम तौर पर ऐसे ऑप्टिमाइज़ेशन होते हैं जो Intel या ARM जैसे खास आर्किटेक्चर को टारगेट करते हैं. साथ ही, इनमें हर आर्किटेक्चर के लिए अलग बैकएंड की ज़रूरत होती है. इस मामले में Wasm एक नया आर्किटेक्चर दिखाता है. अगर वीएम में आर्किटेक्चर के हिसाब से कोई कोड मौजूद है, जैसे कि जस्ट-इन-टाइम (जेआईटी) या अवेयर-ऑफ़-टाइम (एओटी) कंपाइलेशन, तो डेवलपर नए आर्किटेक्चर के लिए जेआईटी/एओटी के लिए बैकएंड भी लागू करता है. यह तरीका काफ़ी सही है, क्योंकि अक्सर हर नए आर्किटेक्चर के लिए कोड बेस का मुख्य हिस्सा फिर से कंपाइल किया जा सकता है.

Wasm का लेवल बहुत कम है. इसलिए, यहां इसी तरीके को आज़माया जा सकता है: मुख्य वीएम कोड को इसके पार्सर, लाइब्रेरी से जुड़ी सहायता, गै़रबेज कलेक्शन, और Wasm के लिए ऑप्टिमाइज़र की मदद से फिर से कंपाइल करें. साथ ही, ज़रूरत पड़ने पर, Wasm के लिए JIT या AOT बैकएंड लागू करें. Wasm MVP के बाद से ऐसा हो पाया है और कई मामलों में यह अच्छी तरह से काम करता है. असल में, Wasm के लिए कंपाइल किया गया PHP WordPress Playground को चलाने में मदद करता है. इस प्रोजेक्ट के बारे में ज़्यादा जानने के लिए, 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 के मौजूदा MVP को लागू करने के बाद, सिर्फ़ संख्याओं, जैसे कि पूर्णांक और फ़्लोट को लीनियर मेमोरी में इस्तेमाल किया जा सकता है. साथ ही, पहचान फ़ाइलों के टाइप के प्रस्ताव शिप किए जाने के बाद, Wasm बाहरी पहचानों को भी रोक सकता है. WasmGC ने अब स्ट्रक्चर और अरे वाले हीप टाइप को जोड़ा है. इसका मतलब है कि अब यह नॉन-लीनियर मेमोरी के साथ काम करता है. हर WasmGC ऑब्जेक्ट का एक तय टाइप और स्ट्रक्चर होता है. इससे वीएम के लिए अपने फ़ील्ड को ऐक्सेस करने के लिए बेहतर कोड जनरेट करना आसान हो जाता है. ऐसा, JavaScript जैसी डाइनैमिक भाषाओं में मौजूद ऑप्टिमाइज़ेशन के जोखिम के बिना किया जाता है. इस प्रस्ताव की मदद से, WebAssembly में मैनेज की जा रही हाई-लेवल भाषाओं के लिए, स्ट्रक्चर और अरे वाले हीप टाइप का बेहतर तरीके से इस्तेमाल किया जा सकता है. इससे Wasm को टारगेट करने वाले लैंग्वेज कंपाइलर को होस्ट वीएम में गार्बेज कलेक्टर के साथ इंटिग्रेट करने की सुविधा मिलती है. आसान शब्दों में इसका मतलब है कि WasmGC के साथ किसी प्रोग्रामिंग भाषा को Wasm में पोर्ट करने का मतलब है कि प्रोग्रामिंग भाषा के गार्बेज कलेक्टर को अब पोर्ट का हिस्सा बनाने की ज़रूरत नहीं है. इसके बजाय, मौजूदा वेस्ट कलेक्टर का इस्तेमाल किया जा सकता है.

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

WasmGC के पोर्ट की गई प्रोग्रामिंग भाषा का इस्तेमाल कैसे किया जा सकता है

कोटलिन वासम

Wasm GC की मदद से, 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 कोड में बुनियादी तौर पर, Kotlin की मदद से बदले गए JavaScript ओएम एपीआई शामिल हैं. यह Compose Multiplatform के साथ बेहतर तरीके से काम करने लगता है. इसकी मदद से, डेवलपर उस यूज़र इंटरफ़ेस (यूआई) को बना सकते हैं जिसे उन्होंने अपने Android Kotlin ऐप्लिकेशन के लिए पहले से बनाया हुआ है. Kotlin/Wasm इमेज व्यूअर डेमो की मदद से इसकी शुरुआती एक्सप्लोरेशन (विश्लेषण का तरीका) देखें और इसके सोर्स कोड को एक्सप्लोर करें. इसी तरह Kotlin टीम के सौजन्य से.

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

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

को दबाकर रखें

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

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

स्वीकार की गई

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