सभी ब्राउज़र पर उपयोगकर्ताओं को बेहतर अनुभव देने के साथ-साथ, WebAssembly की नई सुविधाओं का इस्तेमाल करने का तरीका जानें.
WebAssembly 1.0 को चार साल पहले रिलीज़ किया गया था, लेकिन डेवलपमेंट की प्रोसेस यहीं नहीं रुकी. नई सुविधाएं, सुझाव को स्टैंडर्ड बनाने की प्रोसेस के ज़रिए जोड़ी जाती हैं. आम तौर पर, वेब पर नई सुविधाओं को लागू करने का क्रम और समयसीमा, अलग-अलग इंजन के बीच काफ़ी अलग-अलग हो सकती है. अगर आपको इन नई सुविधाओं का इस्तेमाल करना है, तो आपको यह पक्का करना होगा कि आपके किसी भी उपयोगकर्ता को इन सुविधाओं का ऐक्सेस न छूटे. इस लेख में, आपको ऐसा करने का तरीका पता चलेगा.
कुछ नई सुविधाएं, सामान्य ऑपरेशन के लिए नए निर्देश जोड़कर कोड के साइज़ को बेहतर बनाती हैं. कुछ सुविधाएं, परफ़ॉर्मेंस के बेहतर प्राइमिटिव जोड़ती हैं. वहीं, कुछ सुविधाएं डेवलपर के अनुभव और बाकी वेब के साथ इंटिग्रेशन को बेहतर बनाती हैं.
आधिकारिक रिपॉज़िटरी में, प्रस्तावों की पूरी सूची और उनके अलग-अलग चरणों की जानकारी देखी जा सकती है. इसके अलावा, सुविधा के रोडमैप के आधिकारिक पेज पर जाकर, इंजन में उनके लागू होने की स्थिति को ट्रैक किया जा सकता है.
यह पक्का करने के लिए कि सभी ब्राउज़र के उपयोगकर्ता आपके ऐप्लिकेशन का इस्तेमाल कर सकें, आपको यह तय करना होगा कि आपको किन सुविधाओं का इस्तेमाल करना है. इसके बाद, उन्हें ब्राउज़र के हिसाब से ग्रुप में बांटें. इसके बाद, उन सभी ग्रुप के लिए कोडबेस को अलग-अलग कंपाइल करें. आखिर में, ब्राउज़र की ओर से आपको उन सुविधाओं का पता लगाना होगा जो काम करती हैं. साथ ही, उनसे जुड़े JavaScript और Wasm बंडल को लोड करना होगा.
सुविधाएं चुनना और उन्हें ग्रुप में बांटना
आइए, उदाहरण के तौर पर कोई सुविधा चुनकर, इन चरणों को पूरा करने का तरीका जानें. मान लें कि मैंने यह तय किया है कि मुझे लाइब्रेरी में साइज़ और परफ़ॉर्मेंस की वजहों से, SIMD, थ्रेड, और अपवाद मैनेजमेंट का इस्तेमाल करना है. इन ब्राउज़र पर Google Ads खाता इस्तेमाल किया जा सकता है:
ब्राउज़र को इन कोहॉर्ट में बांटा जा सकता है, ताकि यह पक्का किया जा सके कि हर उपयोगकर्ता को सबसे ऑप्टिमाइज़ किया गया अनुभव मिले:
- Chrome पर आधारित ब्राउज़र: थ्रेड, SIMD, और अपवाद मैनेजमेंट, सभी काम करते हैं.
- Firefox: थ्रेड और SIMD काम करते हैं, लेकिन अपवाद मैनेज करने की सुविधा काम नहीं करती.
- Safari: थ्रेड काम करते हैं, लेकिन SIMD और अपवाद मैनेज करने की सुविधा काम नहीं करती.
- अन्य ब्राउज़र: मान लें कि सिर्फ़ बुनियादी WebAssembly काम करती है.
यह ब्रेकडाउन, हर ब्राउज़र के नए वर्शन में सुविधा के हिसाब से बांटा गया है. मॉडर्न ब्राउज़र हमेशा अप-टू-डेट रहते हैं और अपने-आप अपडेट होते रहते हैं. इसलिए, ज़्यादातर मामलों में आपको सिर्फ़ नए वर्शन की चिंता करनी होती है. हालांकि, जब तक फ़ॉलबैक कोहॉर्ट के तौर पर बेसलाइन WebAssembly को शामिल किया जाता है, तब तक पुराने ब्राउज़र का इस्तेमाल करने वाले लोगों को भी काम करने वाला ऐप्लिकेशन उपलब्ध कराया जा सकता है.
अलग-अलग सुविधाओं के सेट के लिए कंपाइल करना
WebAssembly में, रनटाइम में काम करने वाली सुविधाओं का पता लगाने का कोई तरीका नहीं है. इसलिए, मॉड्यूल में मौजूद सभी निर्देश, टारगेट पर काम करने चाहिए. इसलिए, आपको हर सुविधा के सेट के लिए, सोर्स कोड को Wasm में अलग से कंपाइल करना होगा.
हर टूलचेन और बिल्ड सिस्टम अलग होता है. इन सुविधाओं में बदलाव करने के लिए, आपको अपने कंपाइलर के दस्तावेज़ देखना होगा. आसानी से समझाने के लिए, हम यहां एक फ़ाइल वाली C++ लाइब्रेरी का इस्तेमाल करेंगे. साथ ही, Emscripten की मदद से इसे कंपाइल करने का तरीका भी बताएंगे.
मैं SSE2 इम्यूलेशन के ज़रिए SIMD का इस्तेमाल करूंगा. साथ ही, Pthreads लाइब्रेरी के सपोर्ट की मदद से थ्रेड का इस्तेमाल करूंगा. इसके बाद, Wasm एक्ससेप्शन हैंडल करने और फ़ॉलबैक JavaScript लागू करने में से किसी एक को चुनूंगा:
# First bundle: threads + SIMD + Wasm exceptions
$ emcc main.cpp -o main.threads-simd-exceptions.mjs -pthread -msimd128 -msse2 -fwasm-exceptions
# Second bundle: threads + SIMD + JS exceptions fallback
$ emcc main.cpp -o main.threads-simd.mjs -pthread -msimd128 -msse2 -fexceptions
# Third bundle: threads + JS exception fallback
$ emcc main.cpp -o main.threads.mjs -pthread -fexceptions
# Fourth bundle: basic Wasm with JS exceptions fallback
$ emcc main.cpp -o main.basic.mjs -fexceptions
C++ कोड में #ifdef __EMSCRIPTEN_PTHREADS__
और #ifdef __SSE2__
का इस्तेमाल करके, एक ही फ़ंक्शन के लिए, कॉम्पाइल के समय, पैरलल (थ्रेड और SIMD) और सीरियल लागू करने के बीच, शर्त के हिसाब से चुना जा सकता है. यह इस तरह दिखेगा:
void process_data(std::vector<int>& some_input) {
#ifdef __EMSCRIPTEN_PTHREADS__
#ifdef __SSE2__
// …implementation using threads and SIMD for max speed
#else
// …implementation using threads but not SIMD
#endif
#else
// …fallback implementation for browsers without those features
#endif
}
अपवाद को हैंडल करने के लिए, #ifdef
निर्देशों की ज़रूरत नहीं होती, क्योंकि C++ में भी इसका इस्तेमाल उसी तरह किया जा सकता है. भले ही, कंपाइलेशन फ़्लैग के ज़रिए, लागू करने का कोई भी तरीका चुना गया हो.
सही बंडल लोड करना
सभी सुविधा वाले कोहॉर्ट के लिए बंडल बनाने के बाद, आपको मुख्य JavaScript ऐप्लिकेशन से सही बंडल लोड करना होगा. इसके लिए, सबसे पहले यह पता लगाएं कि मौजूदा ब्राउज़र में कौनसी सुविधाएं काम करती हैं. wasm-feature-detect लाइब्रेरी का इस्तेमाल करके ऐसा किया जा सकता है. इसे डाइनैमिक इंपोर्ट के साथ जोड़कर, किसी भी ब्राउज़र में सबसे ऑप्टिमाइज़ किया गया बंडल लोड किया जा सकता है:
import { simd, threads, exceptions } from 'https://unpkg.com/wasm-feature-detect?module';
let initModule;
if (await threads()) {
if (await simd()) {
if (await exceptions()) {
initModule = import('./main.threads-simd-exceptions.mjs');
} else {
initModule = import('./main.threads-simd.mjs');
}
} else {
initModule = import('./main.threads.mjs');
}
} else {
initModule = import('./main.basic.mjs');
}
const Module = await initModule();
// now you can use `Module` Emscripten object like you normally would
आखिरी बातें
इस पोस्ट में, मैंने अलग-अलग सुविधाओं के सेट के लिए बंडल चुनने, बनाने, और उनमें स्विच करने का तरीका बताया है.
सुविधाओं की संख्या बढ़ने पर,हो सकता है कि सुविधा के कोहॉर्ट की संख्या को मैनेज न किया जा सके. इस समस्या को कम करने के लिए, असल उपयोगकर्ता के डेटा के आधार पर सुविधा वाले कोहॉर्ट चुने जा सकते हैं. साथ ही, कम लोकप्रिय ब्राउज़र को छोड़ा जा सकता है और उन्हें थोड़े कम ऑप्टिमाइज़ किए गए कोहॉर्ट पर वापस लाया जा सकता है. जब तक आपका ऐप्लिकेशन सभी उपयोगकर्ताओं के लिए काम करता है, तब तक इस तरीके से प्रगतिशील बेहतर बनाने की सुविधा और रनटाइम परफ़ॉर्मेंस के बीच एक सही संतुलन बनाया जा सकता है.
आने वाले समय में, WebAssembly में काम करने वाली सुविधाओं का पता लगाने और मॉड्यूल में एक ही फ़ंक्शन के अलग-अलग तरीके से लागू होने के बीच स्विच करने का तरीका पहले से मौजूद हो सकता है. हालांकि, ऐसा तरीका, एमवीपी के बाद की सुविधा होगी. आपको ऊपर बताए गए तरीके का इस्तेमाल करके, इस सुविधा का पता लगाना होगा और इसे शर्तों के हिसाब से लोड करना होगा. तब तक, सभी ब्राउज़र पर WebAssembly की नई सुविधाओं का इस्तेमाल करके कोड बनाने और लोड करने का यह तरीका ही एकमात्र तरीका है.