वेब पर WebAssembly को first-class language बनाना
(hacks.mozilla.org)- WebAssembly 2017 में पहली रिलीज़ के बाद से C/C++ जैसी low-level languages के execution को support करते हुए विकसित हुआ है, लेकिन अब भी वेब प्लेटफ़ॉर्म पर इसे second-class language की तरह माना जाता है
- सिर्फ JavaScript ही Web API के साथ सीधे interact कर सकता है, और WebAssembly को इसके लिए जटिल JS binding code (glue code) लिखना पड़ता है
- यह संरचना loading process की complexity, performance overhead, language-specific toolchain fragmentation जैसी समस्याएँ पैदा करती है, जिससे developer experience खराब होता है
- Mozilla ने इसे हल करने के लिए WebAssembly Component Model प्रस्तावित किया है, जो JS के बिना भी standardized तरीके से Web API calls और module loading संभव बनाता है
- अगर यह मॉडल स्थापित हो जाता है, तो WebAssembly browser के भीतर first-class runtime environment के रूप में जगह बना सकता है, जिससे आम developers भी इसे आसानी से इस्तेमाल कर सकेंगे
WebAssembly को second-class language क्यों माना जाता है
- WebAssembly को web platform access सिर्फ JavaScript के ज़रिए ही मिल सकता है, और उसे सीधे Web API call करने की अनुमति नहीं है
- JavaScript को
<script>टैग से आसानी से load किया जा सकता है, लेकिन WebAssembly के लिए JS API के ज़रिए manual loading process की ज़रूरत होती है WebAssembly.instantiateStreaming()जैसे जटिल API calls करने पड़ते हैं, जिन्हें developers को याद रखना पड़ता है या tools से automate करना पड़ता है
- JavaScript को
- esm-integration proposal JS module system के ज़रिए
.wasmfiles को सीधे import करने की सुविधा देता है, जिससे loading process सरल होती है<script type="module" src="/module.wasm"></script>के रूप में सीधे load किया जा सकता है
Web API access की सीमाएँ
- JavaScript में
console.log("hello, world")की एक लाइन से होने वाला काम, WebAssembly में JS memory access, string decoding, function wrapping जैसी जटिल प्रक्रिया मांगता है- WebAssembly
consoleobject या DOM को access नहीं कर सकता, इसलिए JS में memory sharing और function import/export के ज़रिए indirect calls करनी पड़ती हैं
- WebAssembly
- इस प्रक्रिया में बनने वाला binding code (glue code) हर language में अलग होता है, और
embind,wasm-bindgenजैसे tools से auto-generate किया जाता है- लेकिन इससे build complexity बढ़ती है, runtime overhead आता है, और language-specific incompatibility जैसी समस्याएँ पैदा होती हैं
WebAssembly के first-class language न बन पाने के तकनीकी कारण
- compiler integration की कठिनाई: हर language के compiler को JS और web platform integration code अलग से generate करना पड़ता है, और यह reusable नहीं होता
- standard compiler incompatibility:
rustc --target=wasmसे बनी file browser में सीधे run नहीं होती- platform integration implement करने वाले unofficial toolchains अलग से install करने पड़ते हैं
- documentation ecosystem का bias: MDN जैसे वेब दस्तावेज़ अधिकतर JavaScript-केंद्रित होते हैं, जिससे दूसरी languages के users के लिए entry barrier ऊँचा रहता है
- performance issue: JS binding से होकर जाने वाले DOM calls, direct calls की तुलना में 45% performance drop दिखाते हैं
- Dodrio framework के प्रयोग में JS glue हटाने पर DOM changes लागू करने का समय आधा हो गया
- JavaScript dependency: WebAssembly को production में इस्तेमाल करने के लिए अंततः JS समझना पड़ता है, जो leaky abstraction की समस्या पैदा करता है
WebAssembly Component Model का आगमन
- WebAssembly Component Model कई languages और runtimes में साझा रूप से इस्तेमाल किए जा सकने वाले standardized execution unit को परिभाषित करता है
- Web API access, module loading, और linking process को JS के बिना सीधे किया जा सकता है
- इसे विभिन्न languages से generate किया जा सकता है, और browser या Wasmtime जैसे कई runtimes में run किया जा सकता है
- WIT (Interface Description Language) के ज़रिए ज़रूरी API declare की जा सकती हैं, और उन्हें component के भीतर से सीधे call किया जा सकता है
- उदाहरण:
→ Rust code मेंcomponent { import std:web/console; }console::log("hello, world")call किया जा सकता है
- उदाहरण:
- Browser
<script type="module" src="component.wasm"></script>से component को सीधे load कर सकता है, और JS के बिना Web API binding को अपने आप handle कर सकता है
JavaScript के साथ interoperability
- Component Model hybrid app architecture को भी support करता है
- उदाहरण: image decoder को WebAssembly में लिखकर, JS में
import { Image } from "image-lib.wasm";के रूप में call किया जा सकता है - JS, WebAssembly component को सामान्य module की तरह import/export करके इस्तेमाल कर सकता है
- उदाहरण: image decoder को WebAssembly में लिखकर, JS में
आगे की दिशा और भागीदारी
- Mozilla, WebAssembly CG के साथ मिलकर Component Model standardization पर काम कर रहा है, और Google भी इसकी समीक्षा के चरण में है
- Developers Jco या Wasmtime के माध्यम से browser या CLI में इसका प्रयोग कर सकते हैं
- अगर यह मॉडल स्थापित हो जाता है, तो WebAssembly “power users के फीचर” से आगे बढ़कर ऐसा web technology बन सकता है जिसे आम developers भी इस्तेमाल कर सकें
4 टिप्पणियां
यह तो बस Mozilla-स्टाइल wishful thinking के काफ़ी करीब है। फ्रंटएंड बाज़ार की प्रतिक्रिया वाली limbic system जैसी प्रकृति से संरचनात्मक रूप से बाहर नहीं निकल सकता। WebAssembly आते ही Doom 3 को port कर दिया गया था। DOM आधुनिक ब्राउज़रों में बहुत पहले ही lightweight proxy object में बदल चुका है, और आधुनिक CPU के JavaScript-विशेष instruction set तथा single-core की quantum सीमाओं को देखते हुए, ऐसा कभी नहीं होगा कि यह तरीका बाज़ार-मूल्य के लिहाज़ से बढ़त हासिल करे.
Electron के अंदर चलने वाले WebAssembly binary का क्या मतलब है? यह तो बस किसी और GitKraken CLI या rust porting की शोहरत बटोरने जैसा लगता है।
बाकी बातें छोड़ भी दें, तो
<script type="module" src="/module.wasm"></script>की तरह wasm मॉड्यूल को फ़ाइल के रूप में शामिल करने का तरीका काफ़ी आकर्षक लगता है।और मुझे यह ज़रूर कहना होगा कि WebAssembly की entry barrier बहुत ऊँची होने के दावे बेतुके हैं। बस इतना है कि इसकी ज़रूरत, इसके लिए भुगतान करने की इच्छा से कम है। आपको तेज़ और कम footprint चाहिए, लेकिन साथ में DOM और CSS भी इस्तेमाल करना है? यह कैसी black comedy है।
Hacker News टिप्पणियाँ
WebAssembly में WebIDL सपोर्ट करने के शुरुआती लक्ष्य को छोड़कर एक और IDL बनाने की बात करना, और DOM access की कमी को समस्या न मानना, अफसोसजनक लगा
बेशक मैं बाज़ार की वास्तविकताओं को समझता हूँ, लेकिन खोया हुआ समय खटकता रहता है
संबंधित संदर्भ लिंक: commit रिकॉर्ड, stringref पुनरावलोकन, ACM लेख
बाद में दो और लक्ष्य जोड़े गए: एक non-web API support, दूसरा language interoperability
WebIDL, JS और Web API का union है, इसलिए उसकी expressiveness तो अधिक है, लेकिन उसमें ऐसे कई concept थे जो इन लक्ष्यों से टकराते थे
इसलिए component interface ने expressiveness कम होने के बावजूद कहीं अधिक portable intersection approach चुना
निजी तौर पर मुझे लगता है कि DOM access महत्वपूर्ण है, लेकिन Wasm CG ज़्यादा प्राथमिकता वाले कामों में व्यस्त था
मैंने यह लेख इसलिए लिखा कि लोग जानें, यह समस्या अब भी याद है और इस पर काम जारी रखने की योजना है
toolchain और build process इतने जटिल हैं कि हर बार इस्तेमाल करते समय cognitive load महसूस होता है
performance glue के बिना काफ़ी बेहतर है, लेकिन उतने ही ज़्यादा जोखिम भी हैं
उम्मीद है component model नई complexity नहीं लाएगा, लेकिन कई language examples देखकर लगता है कि काफ़ी भ्रम पहले से ही मौजूद है
खासकर Go उदाहरण में generated files बहुत ज़्यादा हैं, और developer के नज़रिये से tooling simplification बेहद ज़रूरी है
अभी ऐसा लगता है कि complexity हट नहीं रही, बस एक जगह से दूसरी जगह जा रही है
wasm component specification लगातार बदलती रही है, इसलिए churn बहुत रहा है
लक्ष्य यह है कि web developer खुद WIT न लिखें, बल्कि Web API को library की तरह इस्तेमाल कर सकें
लेकिन वहाँ तक पहुँचने में अभी काफ़ी समय लगेगा
उदाहरण के लिए text sharing, media sharing, application sharing जैसी इकाइयों में बाँटा जाए तो security भी बेहतर होगी और छोटी टीमें browser alternatives भी बना सकेंगी
लेकिन विशाल web API और CSS का पैमाना ही browser monopoly को टिकाए रखने वाला तत्व है, इसलिए ऐसी कोशिशें कठिन लगती हैं
अच्छा होगा अगर WebAssembly registry को standardize किया जाए ताकि components को आसानी से compose किया जा सके
आखिरकार web, distributed operating system definition बनाने की प्रक्रिया है
concepts से लेकर code examples तक सब अच्छा व्यवस्थित है
JS ecosystem में StarlingMonkey, ComponentizeJS, jco ये तीन project मुख्य हैं
फिलहाल सबसे mature toolchain Rust की है, लेकिन LLVM-आधारित भाषाओं (C/C++, Go, Python आदि) का support भी लगातार बेहतर हो रहा है
WebAssembly का लक्ष्य local toolchain में स्वाभाविक रूप से घुल-मिल जाने वाला compile target बनना है
अगर अभी भी language-specific glue code या दो runtime models समझने पड़ें, तो WebAssembly अभी भी “सिर्फ चरम परिस्थितियों में इस्तेमाल होने वाला टूल” बना रहेगा
असली बदलाव लाने के लिए सामान्य build path को सरल बनाना होगा
Component Model में यह हिस्सा कैसे संभाला जाता है, यह स्पष्ट नहीं है
DOM हर browser में अलग है, और हर page load पर feature अलग हो सकते हैं
JS bridge layer में polyfill आसानी से लगाया जा सकता है, लेकिन WIT interface में runtime method detection या polyfill कठिन है
performance के अलावा ecosystem की flexibility भी महत्वपूर्ण है
JS glue code को सीधे manage करना या auto-generation tools पर निर्भर रहना, बड़ा पीछे जाना लगता है
Dodrio experiment में glue हटाकर 45% overhead reduction हासिल करना प्रभावशाली था
लेकिन यह जानने की जिज्ञासा है कि WebAssembly Component Model जब Web API के साथ सीधे interact करता है, तब memory management कैसे होता है
क्या Wasm GC proposal का इस्तेमाल DOM references को बनाए रखने में होता है, या अब भी JS GC पर निर्भर रहना पड़ता है?
उम्मीद है Wasm सचमुच एक first-class citizen बन पाएगा
लेकिन अभी IPC फिर भी अप्रभावी है, और मुझे लगता है memory page unit transfer जैसी किसी विधि की ज़रूरत है
किसी को भी मेरे कंप्यूटर पर जटिल प्रोग्राम चलाने देना security के लिहाज़ से पागलपन भरा विचार था, लेकिन हमने वास्तव में ऐसा ही किया
JS की वजह से 20 साल तक countless browser security bugs झेलने पड़े, लेकिन अब design principles और mitigations स्थापित हो चुके हैं
और अब फिर एक और खतरनाक execution paradigm की ओर बढ़ना, विडंबनापूर्ण भी है और सुंदर भी
mobile OS यह काम desktop की तुलना में कहीं बेहतर करते हैं
वे engineer-केंद्रित हैं, और author-friendly default workflow मौजूद नहीं है
फिर भी अच्छा है कि अब भी कुछ लोग इन समस्याओं की परवाह करते हैं
ऐसा लगता है जैसे DOM API को 1:1 map करने के लिए सिर्फ 2x तेज़ string processing हेतु ज़रूरत से ज़्यादा engineering की जा रही है
WebGL2, WebGPU, WebAudio जैसे API में JS shim की लागत पहले ही बहुत मामूली है
असली समस्या GPU buffer copy जैसी जगहों पर है, और component model वहाँ मदद नहीं करता
मैं WebGL2 या WebGPU में दसियों हज़ार draw calls टेस्ट करने वाले benchmarks देखना चाहूँगा
performance के अलावा developer experience (DX) में सुधार भी महत्वपूर्ण है
अभी शुरुआत करना बहुत कठिन है, और लाभ पाने के लिए हर किसी को विशेषज्ञ बनना पड़ता है
अगर यह native app स्तर की efficiency के साथ प्रतिस्पर्धा कर सके, तो web के भविष्य के लिए यह दूरदर्शी बदलाव होगा
coding agent के युग में वे जिस DX सुधार की बात करते हैं, उसका महत्व शायद अब नहीं रहा