दो दशकों से अधिक समय तक JavaScript वेब की निर्विवाद भाषा रही, पर ब्राउज़र का क्रियान्वयन-परिवेश अब एकभाषी नहीं रहा। WebAssembly चुपचाप हर आधुनिक ब्राउज़र का दूसरा क्रियान्वयन-परिवेश बन गया है, और वह ऐसी क्षमताएँ देता है जो JavaScript अकेले कुशलता से नहीं दे सकती। छवि संपादक, वीडियो कोडेक, डेटाबेस इंजन, त्रिआयामी रेंडरर, भाषाओं के क्रियान्वयन-परिवेश — ये सब आज ब्राउज़र के टैब में चल रहे हैं, एक निम्न-स्तरीय द्विआधारी प्रारूप में संकलित, जो लगभग मूल गति से चलता है।
WebAssembly क्या है और क्यों मायने रखता है
WebAssembly एक निम्न-स्तरीय द्विआधारी निर्देश प्रारूप है, जो स्टैक-आधारित आभासी मशीन में चलता है। इसे प्रोग्रामिंग भाषाओं के लिए एक वहनीय संकलन-लक्ष्य के रूप में डिज़ाइन किया गया, ताकि क्लाइंट और सर्वर दोनों तरह के अनुप्रयोग वेब पर तैनात हो सकें। चारों ब्राउज़र निर्माताओं — Google, Mozilla, Apple और Microsoft — ने इसके डिज़ाइन पर मिलकर काम किया, और 2019 में यह W3C का मानक बना। हर प्रमुख ब्राउज़र 2017 से इसका समर्थन करता है।
पर WebAssembly JavaScript का प्रतिस्थापन नहीं, पूरक है। DOM के साथ काम, घटनाओं का प्रबंधन और इंटरफ़ेस का तर्क — ये सब JavaScript की ही भाषा बने रहते हैं। WebAssembly वह गणना-प्रधान काम संभालता है जिसके लिए JavaScript कभी बनी ही नहीं थी। दोनों परिवेश एक ही टैब में साथ रहते हैं: मॉड्यूल JavaScript के फ़ंक्शन आयात करते हैं और JavaScript एक सुपरिभाषित इंटरफ़ेस से Wasm के निर्यात बुलाती है।
WebAssembly का लक्ष्य JavaScript की जगह लेना नहीं है। उसका लक्ष्य उन समस्याओं को हल करना है जिन्हें JavaScript कुशलता से हल नहीं कर पाती। वेब मंच इससे और मज़बूत होता है, क्योंकि डेवलपर एक ही अनुप्रयोग के भीतर हर काम के लिए सही औज़ार चुन सकते हैं।
बुनियाद: द्विआधारी प्रारूप और रैखिक स्मृति
WebAssembly के मॉड्यूल एक द्विआधारी प्रारूप (.wasm फ़ाइलें) उपयोग करते हैं, जो तेज़ विश्लेषण और कम संचरण-आकार के लिए बना है। प्रारूप सघन है: एक सामान्य मॉड्यूल समतुल्य JavaScript से काफ़ी छोटा होता है, लघुकरण के बाद भी। यह प्रकार, फ़ंक्शन, आयात, निर्यात, स्मृति की घोषणाएँ और निर्देश — सबको एक घने प्रतिनिधित्व में कूटबद्ध करता है, जिसे ब्राउज़र एक ही रैखिक चक्कर में जाँचकर संकलित कर सकता है।
हर WebAssembly मॉड्यूल एक वैचारिक स्टैक मशीन पर चलता है। निर्देश मूल्यांकन-स्टैक पर मान चढ़ाते हैं और संक्रियाएँ करने के लिए उन्हें उतारते हैं। समर्थित मान-प्रकार केवल i32, i64, f32 और f64 हैं — 32 और 64 बिट के पूर्णांक तथा दशमलव संख्याएँ। Wasm के स्तर पर न स्ट्रिंग हैं, न ऑब्जेक्ट, न सरणियाँ, न कोई और उच्च-स्तरीय प्रकार। हर जटिल डेटा संरचना को रैखिक स्मृति में कच्चे बाइट के रूप में दर्शाना पड़ता है।
रैखिक स्मृति WebAssembly की सबसे महत्वपूर्ण अवधारणा है। हर मॉड्यूल सतत और आकार बढ़ा सकने वाली स्मृति के एक या अधिक खंड घोषित कर सकता है। यह स्मृति बाइटों की एक सपाट सरणी है, जिसे मॉड्यूल लोड और स्टोर निर्देशों से पढ़ता-लिखता है। मेज़बान — JavaScript का परिवेश या Wasm का परिवेश — आरंभिक और अधिकतम आकार तय करता है और 65,536 बाइट प्रति पृष्ठ के हिसाब से उसे बढ़ा सकता है। मेज़बान की ओर से यह स्मृति ArrayBuffer के रूप में दिखती है, यानी JavaScript ठीक वही स्मृति पढ़ती-लिखती है जिसे मॉड्यूल उपयोग करता है।
यही साझा स्मृति का प्रारूप WebAssembly को कुशल बनाता है। मेज़बान और मॉड्यूल बिना क्रमबद्धीकरण और बिना प्रतिलिपि के डेटा का आदान-प्रदान करते हैं — वे बस एक ही बफ़र में लिखते हैं। जब Rust का कोई फ़ंक्शन JavaScript को कोई स्ट्रिंग लौटाता है, तो वह उसके बाइट रैखिक स्मृति में लिख देता है और एक सूचक (पूर्णांक विस्थापन) तथा एक लंबाई लौटा देता है। JavaScript उन बाइटों को सीधे ArrayBuffer से पढ़ लेती है। न JSON का विश्लेषण, न संदेशों का आदान-प्रदान, न फ़ंक्शन-कॉल से आगे कोई अतिरिक्त भार।
मॉड्यूल की संरचना और सत्यापन
WebAssembly का मॉड्यूल खंडों से बना होता है: प्रकार-खंड फ़ंक्शन के हस्ताक्षर परिभाषित करता है, फ़ंक्शन-खंड फ़ंक्शन घोषित करता है, कोड-खंड में असली बाइटकोड रहता है, स्मृति-खंड रैखिक स्मृति परिभाषित करता है, और निर्यात-खंड फ़ंक्शन तथा स्मृति को मेज़बान के लिए उपलब्ध कराता है। किसी भी मॉड्यूल के चलने से पहले ब्राउज़र उसकी संरचना जाँचता है और प्रकार-सुरक्षा लागू करता है। यह सत्यापन सुनिश्चित करता है कि हर निर्देश के प्रचालक अपेक्षित प्रकार से मेल खाते हैं, हर फ़ंक्शन-कॉल वैध हस्ताक्षर की ओर संकेत करती है, और हर स्मृति-पहुँच घोषित सीमाओं के भीतर रहती है। यह मिलीसेकंडों में हो जाता है और गारंटी देता है कि कोई विकृत मॉड्यूल परिवेश का दुरुपयोग न कर सके।
सुरक्षा का प्रारूप स्पष्ट और सीमित है। जब तक मेज़बान आयातित फ़ंक्शनों के ज़रिये स्पष्ट रूप से क्षमताएँ न दे, WebAssembly का मॉड्यूल न DOM तक पहुँच सकता है, न नेटवर्क अनुरोध कर सकता है, न फ़ाइलें पढ़ सकता है, न सिस्टम से कोई लेन-देन कर सकता है। मॉड्यूल एक बाड़े में चलता है, अपनी रैखिक स्मृति और अपनी आयात-तालिका के बाहर उसकी कहीं पहुँच नहीं। इसी से अविश्वसनीय स्रोतों से आए मॉड्यूल भी सुरक्षित रूप से चलाए जा सकते हैं — ब्राउज़र और सर्वर, दोनों के लिए निर्णायक गुण।
Wasm में संकलन: Rust, C, Go और Zig की तुलना
WebAssembly के लक्ष्य के रूप में संकलन की गुणवत्ता भाषा-दर-भाषा काफ़ी अलग है। कुछ भाषाएँ बहुत कम अतिरिक्त भार के साथ कसे हुए, कुशल मॉड्यूल देती हैं। कुछ को ऐसा परिवेश चाहिए जो द्विआधारी फ़ाइल में मेगाबाइट जोड़ देता है। स्रोत भाषा का चुनाव आपके प्रदर्शन की माँग, टीम की दक्षता और ज़रूरी एकीकरण की जटिलता पर निर्भर है।
Rust: Wasm का स्वर्ण मानक
सब भाषाओं में WebAssembly का सबसे अच्छा समर्थन Rust के पास है। wasm-pack की औज़ार-शृंखला संकलन, अनुकूलन और JavaScript बंधनों का निर्माण निर्बाध रूप से संभाल लेती है। Rust छोटी द्विआधारी फ़ाइलें देती है, क्योंकि उसमें न कचरा-संग्राहक है, न भारी परिवेश, और उसका स्वामित्व-प्रारूप रैखिक स्मृति के प्रबंधन पर स्वाभाविक रूप से बैठता है। कुछ निर्यातित फ़ंक्शनों वाला एक सामान्य Rust मॉड्यूल LTO और अनुकूलन के बाद 10 से 50 KB के बीच रहता है — हाथ से लिखे Wasm के बराबर।
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
extern "C" {
fn alert(s: &str);
}
#[wasm_bindgen]
pub fn fibonacci(n: u32) -> u32 {
match n {
0 => 0,
1 => 1,
_ => fibonacci(n - 1) + fibonacci(n - 2),
}
}
#[wasm_bindgen]
pub fn greet(name: &str) -> String {
format!("Hello, {}! Wasm says hello.", name)
}wasm_bindgen क्रेट ऐसा JavaScript जोड़-कोड बनाता है जो रैखिक स्मृति का सारा नाच अपने आप संभाल लेता है। JavaScript से fibonacci बुलाना किसी भी दूसरे JavaScript फ़ंक्शन को बुलाने जैसा ही लगता है। पर्दे के पीछे wasm_bindgen स्ट्रिंग प्राचलों को «सूचक और लंबाई» के जोड़ों में बदलता है, Wasm फ़ंक्शन बुलाता है और परिणाम को वापस JavaScript स्ट्रिंग में ढाल देता है। यह अमूर्तन की परत बहुत कम भार जोड़ती है और Rust तथा Wasm के मेल को रोज़मर्रा के काम लायक़ बना देती है।
Emscripten के ज़रिये C और C++
Emscripten Wasm के लिए मूल संकलन-शृंखला है। यह LLVM को पिछले सिरे पर रखकर C और C++ कोड को Wasm में संकलित करती है, और POSIX के साथ एक व्यापक संगतता-परत देती है, जिससे मौजूदा मूल अनुप्रयोगों को स्रोत में न्यूनतम बदलाव के साथ वेब पर लाया जा सकता है। इसमें आभासी फ़ाइल सिस्टम, OpenGL से WebGL में अनुवाद, pthread का अनुकरण, और मॉड्यूल की जीवन-चक्र संभालने वाला JavaScript परिवेश शामिल है।
Go और उसका आधिकारिक Wasm पिछला सिरा
Go ने 1.11 में WebAssembly का समर्थन जोड़ा और हर रिलीज़ के साथ उसे बेहतर करती रही है। Go का कार्यक्रम Wasm में संकलित करना सीधा है — GOOS=js GOARCH=wasm तय कीजिए और go build चलाइए। पर Rust की तुलना में Go के समर्थन की सीमाएँ स्पष्ट हैं। Go हर द्विआधारी फ़ाइल में अपना परिवेश (goroutine का अनुसूचक, कचरा-संग्राहक, defer का स्टैक) शामिल कर देती है, इसलिए एक न्यूनतम मॉड्यूल भी लगभग 2 MB से शुरू होता है। सर्वर पर यह स्वीकार्य है, जहाँ आकार कम मायने रखता है, पर ब्राउज़र में, जहाँ डाउनलोड और विश्लेषण का समय निर्णायक है, यह बहुत भारी पड़ता है।
Zig: नया दावेदार
Zig ख़ुद को C के आधुनिक विकल्प के रूप में रखती है, जिसमें WebAssembly का प्रथम-श्रेणी समर्थन है। Zig का संकलक Emscripten जैसे आवरण के बिना सीधे Wasm को लक्ष्य बना सकता है। यह आकार और प्रदर्शन में Rust के बराबर मॉड्यूल देती है, और उसकी comptime सुविधा ऐसी मेटा-प्रोग्रामिंग देती है जो क्रियान्वयन-समय का भार पूरी तरह हटा सकती है। जब तक आप स्वयं न जोड़ें, Zig कोई छिपा हुआ परिवेश साथ नहीं लाती — न कचरा-संग्राहक, न आवंटक, न आरंभिक कोड।
- Rust सबसे छोटी Wasm द्विआधारी फ़ाइलें देती है (सामान्य मॉड्यूल के लिए 10–50 KB) और wasm-pack तथा wasm-bindgen के साथ सबसे अच्छी औज़ार-दुनिया रखती है।
- Emscripten के ज़रिये C और C++ मौजूदा मूल कोडबेस को Wasm में लाने का सबसे अच्छा रास्ता हैं — संगतता सर्वाधिक, पर फ़ाइलें बड़ी।
- Go आसानी से Wasm में संकलित होती है, पर अंतर्निहित परिवेश के कारण बड़ी फ़ाइलें (2 MB से अधिक) देती है, इसलिए सर्वर पर अधिक उपयुक्त है।
- Zig बिना परिवेश-भार के कसे हुए मॉड्यूल देती है और न्यूनतम या अंतःस्थापित उपयोगों के लिए आदर्श है।
ब्राउज़र में Wasm का उपयोग
ब्राउज़र में WebAssembly मॉड्यूल लादना और चलाना एक मानक इंटरफ़ेस का अनुसरण करता है, जो सभी आधुनिक ब्राउज़रों में एक जैसा है। JavaScript का इंटरफ़ेस WebAssembly नामस्थान में compile, instantiate और instantiateStreaming देता है। प्रवाही रूप बेहतर है, क्योंकि वह बाइटों के उतरते ही संकलन शुरू कर देता है और नेटवर्क के काम को संकलन के साथ ओवरलैप कर देता है।
async function loadWasm(url: string) {
const response = await fetch(url);
const results = await WebAssembly.instantiateStreaming(response);
return results.instance.exports;
}
async function main() {
const wasm = await loadWasm("/fibonacci.wasm");
console.log(wasm.fibonacci(40));
}
main().catch(console.error);instantiateStreaming एक ऐसा ऑब्जेक्ट लौटाता है जिसमें instance गुण (संकलित मॉड्यूल का उदाहरण) और exports ऑब्जेक्ट होता है, जिसमें मॉड्यूल के निर्यात के रूप में घोषित सभी फ़ंक्शन और स्मृति रहती है। दूसरे तर्क के रूप में imports ऑब्जेक्ट भी दिया जा सकता है, जो मॉड्यूल को वे JavaScript फ़ंक्शन और मान देता है जिनकी वह संकलन के समय अपेक्षा कर रहा था।
उत्पादन में आमतौर पर मॉड्यूल को निर्माण-चरण में पहले ही संकलित कर लिया जाता है, या बंडलर का प्लगइन उपयोग होता है। Webpack 5 Wasm के आयात को सीधे समझता है, Vite में समर्थन प्रायोगिक है। ये बंडलर लाना, उदाहरण बनाना और जीवन-चक्र संभालना अपने आप कर लेते हैं, जिससे Wasm मॉड्यूल को JavaScript मॉड्यूल की तरह आयात किया जा सकता है। wasm-pack के साथ आयात का ढर्रा इस तरह दिखता है: import init from './pkg/fibonacci.js', जो एक प्रॉमिस-आधारित आरंभीकरण फ़ंक्शन देता है, जो सारा जोड़-कोड संभाल लेता है।
ब्राउज़र में एक निर्णायक बात पहला संकलन है। मॉड्यूल पहली बार लादे जाने पर द्विआधारी प्रारूप से मूल कोड में संकलित होते हैं। छोटे मॉड्यूल में यह कुछ मिलीसेकंड लेता है। बड़े मॉड्यूल में — 10 MB से ऊपर — इसमें कई सौ मिलीसेकंड लग सकते हैं और मुख्य धागा रुक सकता है। समाधान है Web Worker में WebAssembly.compileStreaming का उपयोग: संकलन मुख्य धागे से बाहर होता है और एक संकलित मॉड्यूल-ऑब्जेक्ट लौटाता है, जिसका उदाहरण मुख्य धागा तुरंत बना लेता है। बड़े मॉड्यूल लादने वाले अनुप्रयोगों के लिए यह ढर्रा अनिवार्य है।
WASI और सर्वर पर Wasm
WebAssembly मूलतः केवल ब्राउज़र के लिए बना था, पर उसका सुरक्षा-प्रारूप और प्रदर्शन के गुण उसे सर्वर पर भी उतना ही आकर्षक बनाते हैं। कठिनाई यह है कि ब्राउज़र विशिष्ट मेज़बान-इंटरफ़ेस देता है — DOM, fetch, WebSocket — जो सर्वर के परिवेशों में नहीं होते। WebAssembly System Interface इसे हल करता है: वह POSIX जैसे तंत्र-कॉलों का एक मानक समुच्चय परिभाषित करता है, जिन्हें मॉड्यूल ब्राउज़र के बाहर उपयोग कर सकते हैं।
WASI फ़ाइल के इनपुट-आउटपुट, नेटवर्क, घड़ी तक पहुँच, यादृच्छिक संख्याओं, पर्यावरण-चरों और कमांड-लाइन तर्कों के लिए अमूर्तन देता है। WASI समर्थन के साथ संकलित मॉड्यूल फ़ाइलें पढ़ सकता है, नेटवर्क सॉकेट खोल सकता है और एक मानकीकृत इंटरफ़ेस से ऑपरेटिंग सिस्टम से बात कर सकता है, जो किसी भी WASI-अनुरूप परिवेश में काम करता है। सर्वर अनुप्रयोग के रूप में Wasm चलाने की बुनियाद यही है।
WASI का मानक कई क्रमिक स्नैपशॉट से आगे बढ़ रहा है। WASI preview 1 वह स्थिर आधार है जिसे आज अधिकांश औज़ार-शृंखलाएँ समर्थन देती हैं। WASI preview 2 घटक-प्रारूप के अनुरूप डिज़ाइन और क्षमता-आधारित सुरक्षा लाता है, जहाँ हर मॉड्यूल स्पष्ट रूप से बताता है कि उसे कौन-से तंत्र-संसाधन चाहिए। preview 2 एक महत्वपूर्ण वास्तु-सुधार है, क्योंकि यह बारीक अनुमति-प्रारूप संभव बनाता है — जिस मॉड्यूल को केवल एक ख़ास फ़ाइल पढ़नी है, वह तंत्र की किसी और फ़ाइल तक पहुँच ही नहीं सकता।
WASI WebAssembly को ब्राउज़र की तकनीक से एक सार्वभौमिक, बाड़े में चलने वाले परिवेश में बदल देता है। जो मॉड्यूल ब्राउज़र के टैब में चलता है, वही सर्वर के Wasm परिवेश में, बिना-सर्वर फ़ंक्शन में, या किसी किनारे की गाँठ पर भी चल सकता है — बिना किसी बदलाव के। «एक बार लिखो, कहीं भी चलाओ» का अर्थ तब नया हो जाता है, जब उस «कहीं भी» में वे परिवेश भी आ जाएँ जहाँ JavaScript नहीं पहुँचती।
Wasm के परिवेश और तैनाती
ब्राउज़र के बाहर WebAssembly चलाने के लिए सर्वर का Wasm परिवेश चाहिए। कई परिपक्व विकल्प हैं, हर एक के अपने डिज़ाइन-दर्शन और उपयोग। तीन सबसे महत्वपूर्ण हैं Wasmtime, Wasmer, और अंतःस्थापित तंत्रों के लिए WAMR (WebAssembly Micro Runtime)।
Wasmtime
Wasmtime एक स्वतंत्र परिवेश है, जिसे Bytecode Alliance ने बनाया — वही संस्था जो WASI मानक को आगे बढ़ाती है। यह Rust में लिखा है, मॉड्यूल को Cranelift (ख़ास Wasm के लिए बना कोड-जनक) से संकलित करता है, और Rust, C, Python तथा अन्य भाषाओं के इंटरफ़ेस देता है। सर्वर पर Wasm के लिए यह सबसे अधिक उपयोग होने वाला परिवेश है, और Cloudflare Workers, Fastly Compute@Edge तथा कई अन्य किनारे-गणना मंचों के पीछे यही है।
use wasmtime::*;
fn main() -> Result<()> {
let engine = Engine::default();
let module = Module::from_file(&engine, "hello.wasm")?;
let mut store = Store::new(&engine, ());
let instance = Instance::new(&mut store, &module, &[])?;
let hello = instance
.get_typed_func::<(), ()>(&mut store, "hello")?;
hello.call(&mut store, ())?;
Ok(())
}Wasmtime का अंतःस्थापन-इंटरफ़ेस साफ़ और सहज है। आप एक Engine (संकलन-परिवेश) बनाते हैं, फ़ाइल या बाइटों से Module लादते हैं, एक Store (क्रियान्वयन-संदर्भ, जो Wasm की रैखिक स्मृति रखता है) बनाते हैं, और मॉड्यूल का उदाहरण बनाकर उसके निर्यातित फ़ंक्शनों तक पहुँचते हैं। स्मृति-प्रबंधन, फंदों का प्रबंधन और WASI तंत्र-कॉलों का आगे भेजना — सब परिवेश अपने आप संभालता है।
Wasmer
Wasmer एक और लोकप्रिय परिवेश है, जो कई संकलन-पिछले-सिरों का समर्थन करता है — Cranelift, LLVM और Singlepass (कम अनुकूलन के साथ तेज़ JIT संकलन)। Wasmer Rust, C, C++, Python, Go, PHP, Ruby, Java और अन्य के लिए SDK देता है, जिससे वह लगभग किसी भी प्रोग्रामिंग परिवेश से सुलभ हो जाता है। साथ ही वह Wasm मॉड्यूल बाँटने के लिए एक पैकेज-पंजी (WAPM) भी देता है, npm की तरह।
मुख्य अंतर यह है कि Wasmer डेवलपर के अनुभव और अंतःस्थापन की सरलता पर ज़ोर देता है, जबकि Wasmtime मानक के पालन और सुरक्षा पर। दोनों बेहतरीन विकल्प हैं; चुनाव इस पर टिकता है कि आप दुनिया की चौड़ाई (Wasmer) को अधिक मूल्य देते हैं या विनिर्देश के कड़े पालन और उत्पादन के रिकॉर्ड (Wasmtime) को।
- Wasmtime: उत्पादन में सर्वर-पक्षीय Wasm के लिए सर्वोत्तम, WASI का कड़ा पालन, Cranelift JIT संकलक, Cloudflare और Fastly में उपयोग।
- Wasmer: Rust से इतर अनुप्रयोगों में Wasm अंतःस्थापित करने के लिए सर्वोत्तम, लगभग मूल गति के लिए LLVM संकलन का समर्थन, और WAPM की पैकेज-दुनिया।
- WAMR: इंटरनेट ऑफ़ थिंग्स और अंतःस्थापित उपकरणों के लिए सर्वोत्तम, बेहद छोटा पदचिह्न, विवेचक और JIT दोनों विधियाँ, और iwasm कमांड-लाइन औज़ार।
प्रदर्शन के गुण और Wasm कब जीतता है
JavaScript पर WebAssembly की प्रदर्शन-बढ़त काम की प्रकृति पर निर्भर है। CPU से बँधे, गणना-प्रधान कामों में Wasm आमतौर पर 1.5 से 3 गुना तेज़ चलता है। छवि-प्रसंस्करण या संपीड़न जैसे स्मृति-प्रधान कामों में बढ़त और बड़ी हो सकती है, क्योंकि Wasm स्मृति की सजावट और आवंटन के ढर्रे को सीधे नियंत्रित करता है। जिन कामों में इनपुट-आउटपुट या DOM हावी हो, वहाँ Wasm का कोई लाभ नहीं, बल्कि मॉड्यूल और JavaScript मेज़बान के बीच के पुल के कारण अतिरिक्त भार भी जुड़ सकता है।
संकलन का प्रारूप भी मायने रखता है। JavaScript JIT संकलन का उपयोग करती है: कोड तुरंत चलने लगता है और गर्म रास्ते समय के साथ अनुकूलित होते हैं। Wasm पहले से या मॉड्यूल लादते समय संकलित होता है, इसलिए वह शुरुआत से ही अपनी सर्वोच्च गति पर होता है — कोई तपने का दौर नहीं। कम जीवन वाले फ़ंक्शनों या एक बार के क्रियान्वयन में इससे JIT के तपने की वह देरी हट जाती है, जो पहली बार बुलाने पर JavaScript को धीमा कर देती है।
Wasm असल में पूर्वानुमेयता में उत्कृष्ट है। JavaScript का JIT अनुकूलन नियतात्मक नहीं है: वही फ़ंक्शन प्राप्त प्रकारों, बुलाए जाने की संख्या और संकलक के अनुमानी नियमों की मौजूदा स्थिति के अनुसार अनुकूलित या अ-अनुकूलित हो सकता है। Wasm का क्रियान्वयन नियतात्मक है। हर निर्देश की लागत निश्चित है। न कचरा-संग्रह का ठहराव, न प्रकारों का भ्रम, न अनुकूलन से पीछे हटना। इसीलिए जहाँ विलंब की एकरूपता सैद्धांतिक अधिकतम प्रवाह से अधिक मायने रखती है — ध्वनि प्रसंस्करण, भौतिक अनुकरण, वित्तीय गणनाएँ — वहाँ Wasm सही चुनाव है।
- Wasm यहाँ जीतता है: छवि और वीडियो प्रसंस्करण, ध्वनि का संश्लेषण और विश्लेषण, डेटा का संपीड़न और विसंपीड़न, कूटलेखन की संक्रियाएँ, खेल-इंजन, भौतिक अनुकरण, डेटाबेस प्रश्नों का क्रियान्वयन।
- JavaScript यहाँ जीतती है: DOM के साथ काम, घटनाओं का प्रबंधन, नेटवर्क अनुरोधों का समन्वय, ढाँचों से इंटरफ़ेस की रचना, स्ट्रिंग और पाठ का प्रसंस्करण, छोटी या कम बुलाई जाने वाली उपयोगिताएँ।
- सीमा खिसक रही है: WASI और घटक-प्रारूप से जैसे-जैसे Wasm को वेब इंटरफ़ेस मिलते हैं, और काम उसकी ओर जाते हैं, पर JavaScript मुख्य इंटरफ़ेस-परत बनी रहती है।
घटक-प्रारूप और Wasm का भविष्य
WebAssembly का घटक-प्रारूप उसकी पहली रिलीज़ के बाद का सबसे महत्वपूर्ण विकास है। यह आरंभिक Wasm की बुनियादी सीमा पर काम करता है: मॉड्यूल अलग-थलग कोठरियाँ थे, जिनके बीच जुड़ने का कोई मानक तरीक़ा नहीं था। घटक-प्रारूप एक उच्च-स्तरीय, भाषा-निरपेक्ष इंटरफ़ेस-व्यवस्था लाता है, जिससे Wasm मॉड्यूल को ईंटों की तरह जोड़ा जा सकता है।
मौजूदा प्रारूप में मॉड्यूल केवल ऐसे फ़ंक्शन निर्यात करता है जो पूर्णांक और दशमलव ही लेते-देते हैं। अगर किसी मॉड्यूल को दूसरे तक स्ट्रिंग, सरणी या कोई जटिल संरचना पहुँचानी हो, तो दोनों को स्मृति की सजावट पर सहमत होना पड़ता है — रैखिक स्मृति का एक क्षेत्र साझा करना और आवंटन-मुक्ति का तालमेल बिठाना। यह नाज़ुक है और भाषा पर निर्भर। घटक-प्रारूप इसे इंटरफ़ेस-प्रकारों की एक मानकीकृत व्यवस्था से हल करता है, जो स्ट्रिंग, रिकॉर्ड, विविध, सूची और नेस्टेड संरचनाओं को मॉड्यूल की सीमाओं के आर-पार संभालती है।
इंटरफ़ेस-प्रकार घटकों के बीच बहने वाले डेटा का वर्णन भाषा-निरपेक्ष ढंग से करते हैं। कोई घटक ऐसा फ़ंक्शन निर्यात कर सकता है जो स्ट्रिंग लेकर दो पूर्णांक क्षेत्रों वाला रिकॉर्ड लौटाए, और कोई भी दूसरा घटक — चाहे वह Rust में लिखा हो, C में या Go में — उसे बुला सकता है, बिना यह जाने कि सामने वाले की आंतरिक स्मृति-सजावट कैसी है। परिवेश अनुकूलन का तर्क अपने आप बना लेता है और बुलाने वाले तथा बुलाए जाने वाले के प्रतिनिधित्व के बीच अनुवाद करता है।
वास्तविक उदाहरण
WebAssembly कोई सैद्धांतिक तकनीक नहीं है। यह आज उत्पादन में चल रहे कुछ सबसे माँगदार वेब अनुप्रयोगों को चला रहा है, और जैसे-जैसे औज़ार परिपक्व होते हैं और प्रदर्शन के लाभ अकाट्य होते जाते हैं, इसका प्रसार तेज़ हो रहा है।
Figma: Wasm का अग्रदूत
Figma सबसे प्रसिद्ध सफलता की कहानी है। उसका मूल रेंडरिंग इंजन C++ में लिखा है और Emscripten से Wasm में संकलित होता है। Figma अपनी पूरी C++ कोडबेस — जिसमें Skia ग्राफ़िक्स लाइब्रेरी, HarfBuzz पाठ-आकारक और अपना लेआउट इंजन शामिल है — एक Wasm मॉड्यूल में संकलित करती है। JavaScript की परत इनपुट की घटनाएँ और DOM संभालती है, जबकि Wasm सारा रेंडरिंग, हिट-परीक्षण और लेआउट की गणनाएँ करता है। नतीजा एक ऐसा डिज़ाइन औज़ार है जो ब्राउज़र के टैब में चलता है और जिसका प्रदर्शन मूल डेस्कटॉप अनुप्रयोगों की टक्कर का है।
SQLite: ब्राउज़र में डेटाबेस
SQLite शायद दुनिया में सबसे व्यापक रूप से तैनात Wasm मॉड्यूल है। परियोजना एक आधिकारिक Wasm निर्माण जारी करती है, जो पूरा SQLite इंजन ब्राउज़र में चलाता है। उपयोगकर्ता बिना किसी सर्वर-घटक के, पूरी तरह क्लाइंट पर ही SQLite डेटाबेस से प्रश्न कर सकते हैं। यह निर्माण Emscripten की औज़ार-शृंखला से बनता है और डेटाबेस को IndexedDB में टिकाए रखने के लिए आभासी फ़ाइल-सिस्टम का समर्थन रखता है।
इसके निहितार्थ बड़े हैं। जिन अनुप्रयोगों को क्लाइंट पर प्रश्न करने की क्षमता चाहिए — डेटा विश्लेषण के औज़ार, रिपोर्टिंग के पटल, वैज्ञानिक गणना की नोटबुक — वे Wasm में SQLite से जटिल समुच्चयन, जोड़ और विंडो फ़ंक्शन सीधे ब्राउज़र में चला सकते हैं, बिना डेटा किसी सर्वर को भेजे। sql.js और better-sqlite3-wasm जैसी लाइब्रेरियाँ SQLite के Wasm मॉड्यूल को साफ़-सुथरे JavaScript इंटरफ़ेस में लपेट देती हैं, जिससे उसका उपयोग किसी भी npm पैकेज जितना आसान हो जाता है।
Google Earth: त्रिआयामी रेंडरिंग के लिए Wasm
ब्राउज़र के लिए Google Earth को त्रिआयामी भूभाग के प्रसंस्करण और डेटा-विसंपीड़न की शृंखलाओं के लिए Wasm से दोबारा बनाया गया। जैसे-जैसे उपयोगकर्ता घूमता है, Wasm मॉड्यूल संपीड़ित द्विआधारी डेटा पाता है, उसे Wasm में संकलित अनुकूलित C++ एल्गोरिदम से खोलता है, ज्यामिति को रेंडर करने योग्य जालों में बदलता है, और परिणाम WebGL को सौंप देता है — यह सब एक ही ऐनिमेशन फ़्रेम के बजट के भीतर और बिना किसी डेटा-प्रतिलिपि के भार के।
- Figma अपने C++ रेंडरिंग इंजन के लिए Wasm उपयोग करती है और ब्राउज़र में वेक्टर ग्राफ़िक्स संपादन में मूल स्तर का प्रदर्शन पाती है।
- SQLite एक आधिकारिक Wasm निर्माण देती है, जो पूरा डेटाबेस इंजन क्लाइंट पर चलाता है और बिना सर्वर के ऑफ़लाइन प्रश्न संभव बनाता है।
- Google Earth बहते भू-स्थानिक डेटा के वास्तविक-समय विसंपीड़न और ज्यामिति-प्रसंस्करण के लिए Wasm पर टिका है, 60 फ़्रेम प्रति सेकंड पर।
- Adobe वेब के Photoshop में छवि-फ़िल्टर और रंग-अवकाश परिवर्तनों के लिए Wasm (Emscripten से संकलित C++ कोड) उपयोग करती है।
- Zoom अपने वेब क्लाइंट में वीडियो के विकोडन और पृष्ठभूमि धुँधलाने के लिए Wasm उपयोग करता है।
किनारे पर और बिना-सर्वर परिवेश में Wasm
बिना-सर्वर मंचों ने किनारे की गणना के लिए WebAssembly को इसलिए अपनाया कि कंटेनरों की तुलना में उसका ठंडा प्रारंभ बेहतर है। Wasm मॉड्यूल माइक्रोसेकंडों में शुरू होता है — मिलीसेकंडों में नहीं — क्योंकि न कोई ऑपरेटिंग सिस्टम चालू करना है, न कोई प्रक्रिया बाँटनी है, न कोई परिवेश आरंभ करना है। जिन मंचों पर ठंडे प्रारंभ का विलंब सीधे उपयोगकर्ता के अनुभव को छूता है, उनके लिए यह गुणात्मक बदलाव है।
Cloudflare Workers Wasm अपनाने वाला पहला बड़ा मंच था। Workers V8 के अलगावों में चलते हैं, जो JavaScript और Wasm दोनों चला सकते हैं। जो Worker अपनी गणना का तर्क Wasm मॉड्यूल में रखता है, वह ठंडे प्रारंभ के बाद 5 मिलीसेकंड से कम में अनुरोध संभालना शुरू कर सकता है। Worker का परिवेश Service Worker के विनिर्देश पर आधारित सीमित इंटरफ़ेस देता है — fetch, Cache, KV भंडारण और Durable Objects — और WASI समर्थन के साथ संकलित Wasm मॉड्यूल मेज़बान के आयात-तंत्र से उन्हें उपयोग कर सकते हैं।
Fastly का Compute@Edge Wasmtime को मूल परिवेश बनाता है और सभी गणनाओं को Wasm में संकलित करने की माँग करता है। डेवलपर अपना किनारे का तर्क Rust, Go या JavaScript में लिखते हैं (जिसे Fastly पहले ही Wasm में संकलित कर देती है), और बना हुआ मॉड्यूल Fastly की किनारे की गाँठों पर चलता है। यह प्रारूप मज़बूत सुरक्षा-अलगाव देता है — हर अनुरोध एक नए Wasm उदाहरण में चलता है, बिना साझा अवस्था के — और साथ ही वह प्रारंभ-गति देता है जो किनारे की गणना को व्यावहारिक बनाती है।
किनारे पर Wasm की दुनिया अभी युवा है, पर तेज़ी से बढ़ रही है। Fermyon Spin और Deislabs जैसे मंच बिना-सर्वर Wasm अनुप्रयोग बनाने के लिए ख़ास ढाँचे देते हैं। ये WASI परिवेश की बारीकियाँ छिपा देते हैं और जाने-पहचाने ढर्रे देते हैं — HTTP संचालक, कुंजी-मान भंडारण, निर्धारित कार्य — जबकि सब कुछ Wasm से ही चलता है। वादा यह है कि आप अपना व्यापार-तर्क एक बार, Wasm में संकलित होने वाली किसी भी भाषा में लिखें, और उसे बिना बदलाव के किसी भी WASI-संगत मंच पर तैनात कर दें।
आज Wasm के साथ शुरुआत कैसे करें
शुरुआत का सबसे अच्छा तरीक़ा आपके लक्ष्य पर निर्भर है। अगर ब्राउज़र में Wasm चाहिए, तो सबसे तेज़ रास्ता है Rust और wasm-pack। Rust स्थापित कीजिए, wasm32-unknown-unknown लक्ष्य जोड़िए, और wasm-pack new से नया प्रोजेक्ट बनाइए। बना हुआ प्रोजेक्ट एक चलता-फिरता उदाहरण देता है, जिसमें JavaScript से बुलाया जा सकने वाला Wasm फ़ंक्शन, npm-संगत पैकेज बनाने वाली निर्माण-स्क्रिप्ट, और आपके मॉड्यूल को बिना-परदे के ब्राउज़र में चलाने वाला परीक्षण-ढाँचा शामिल है।
अगर सर्वर पर Wasm देखना है, तो Wasmtime और उसके कमांड-लाइन औज़ार से शुरू कीजिए। wasmtime स्थापित कीजिए, WASI समर्थन के साथ कोई भी C या Rust कार्यक्रम संकलित कीजिए, और उसे wasmtime program.wasm से चलाइए। आप देखेंगे कि Wasm में संकलित एक कमांड-लाइन कार्यक्रम बिल्कुल मूल द्विआधारी फ़ाइल की तरह व्यवहार करता है — वह मानक इनपुट से पढ़ता है, मानक आउटपुट पर लिखता है, फ़ाइलों तक पहुँचता है और एक स्थिति-कोड के साथ समाप्त होता है। टर्मिनल में Wasm कार्यक्रम चलाने का अनुभव हैरान कर देने वाली तरह सहज है।
किनारे और बिना-सर्वर के प्रयोग के लिए Cloudflare Workers एक मुफ़्त स्तर देता है जो Wasm का समर्थन करता है। Rust में एक फ़ंक्शन लिखिए, उसे Wasm में संकलित कीजिए, और Cloudflare के वैश्विक जाल पर तैनात कर दीजिए। आप अधिकांश स्थानों से 10 मिलीसेकंड से कम की प्रतिक्रिया देखेंगे, और ख़ुद अनुभव करेंगे कि Wasm ठंडे प्रारंभ की चिंता को कैसे मिटा देता है।
Wasm के साथ सबसे व्यावहारिक पहला क़दम अपना पूरा अनुप्रयोग दोबारा लिखना नहीं है। एक गणना-महँगा फ़ंक्शन खोजिए — कोई फ़िल्टर, कोई रूपांतरण, कोई जाँच — उसे Rust में दोबारा लिखिए, Wasm में संकलित कीजिए, और अपनी मौजूदा कोडबेस में जोड़ दीजिए। फिर अंतर मापिए। जब आप पचास पंक्तियों के Wasm से तीन गुना तेज़ी देखेंगे, तब समझ आएगा कि यह तकनीक क्यों मायने रखती है।
औज़ारों का परिदृश्य तेज़ी से सुधर रहा है। wasm-pack, cargo-generate और wasm-tools एक परिपक्व कार्य-प्रवाह देते हैं। Binaryen की शृंखला में wasm-opt मॉड्यूल को अनुकूलित करके आकार 20 से 30 प्रतिशत घटा देता है। Wasmtime और Wasmer मूल क्रियान्वयन से दूरी लगातार कम कर रहे हैं। और घटक-प्रारूप जल्द ही Wasm मॉड्यूल को इस तरह परस्पर-संचालनीय बना देगा, जो Wasm के आरंभ में असंभव था।
WebAssembly उस वेब का प्रतिस्थापन नहीं जिसे हम जानते हैं। यह मंच का संवर्धन है — एक दूसरा परिवेश, जो वह करता है जो JavaScript नहीं कर सकती। अगली बार जब आप किसी प्रदर्शन की समस्या से जूझें और लगे कि आप JavaScript की गतिशील प्रकृति से लड़ रहे हैं, तो सोचिए कि कोड का गणना-प्रधान हिस्सा किसी Wasm मॉड्यूल में निकाला जा सकता है या नहीं। औज़ार उत्पादन के लायक़ हैं, प्रदर्शन का लाभ असली है, और Wasm का भविष्य — घटक-प्रारूप, WASI preview 2 और भाषाओं के व्यापक समर्थन के साथ — और बेहतर ही होता जा रहा है।
वेब मंच को विस्तार-योग्य बनाने के लिए ही रचा गया था। WebAssembly एक दशक में उसका सबसे महत्वपूर्ण विस्तार है। जो डेवलपर ऐसे अनुप्रयोग बनाना चाहते हैं जो वेब की सीमाओं को आगे धकेलें, उनके लिए इसे समझना वैकल्पिक नहीं है।