WebAssembly सुविधा का पता लगाने की सुविधा

सभी ब्राउज़र पर उपयोगकर्ताओं की मदद करते हुए, WebAssembly की नई सुविधाओं को इस्तेमाल करने का तरीका जानें.

WebAssembly 1.0 को चार साल पहले रिलीज़ किया गया था. हालांकि, इसके डेवलपमेंट के बाद भी इसमें बढ़ोतरी हुई. नई सुविधाएं प्रपोज़ल स्टैंडर्ड तय करने की प्रोसेस के ज़रिए जोड़ी जाती हैं. आम तौर पर, वेब पर मौजूद नई सुविधाओं की तरह ही, अलग-अलग इंजन के लिए इन सुविधाओं को लागू करने का क्रम और टाइमलाइन अलग-अलग हो सकती हैं. अगर आपको उन नई सुविधाओं का इस्तेमाल करना है, तो आपको यह पक्का करना होगा कि आपका कोई भी उपयोगकर्ता छूट न जाए. इस लेख में, ऐसा करने का तरीका बताया गया है.

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

प्रस्तावों की पूरी सूची और उनसे जुड़े स्टेज आधिकारिक रेपो में देखे जा सकते हैं. इसके अलावा, सुविधा के रोडमैप के आधिकारिक पेज पर, इंजन में उन्हें लागू किए जाने की स्थिति को ट्रैक किया जा सकता है.

यह पक्का करने के लिए कि सभी ब्राउज़र के उपयोगकर्ता आपके ऐप्लिकेशन का इस्तेमाल कर सकें, आपको पता लगाना होगा कि आपको किन सुविधाओं का इस्तेमाल करना है. इसके बाद, ब्राउज़र पर काम करने की सुविधा के हिसाब से उन्हें अलग-अलग ग्रुप में बांटें. इसके बाद, ऐसे हर ग्रुप के लिए अपने कोड बेस को अलग-अलग कंपाइल करें. आखिर में, ब्राउज़र की ओर से आपको समर्थित सुविधाओं का पता लगाने और संबंधित JavaScript और Wasm बंडल को लोड करने की ज़रूरत होगी.

सुविधाएं चुनना और ग्रुप बनाना

आइए, उदाहरण के तौर पर किसी आर्बिट्रेरी सुविधा सेट को चुनकर उन चरणों के बारे में जानते हैं. मान लें कि मुझे पता चला है कि मुझे साइज़ और परफ़ॉर्मेंस की वजहों के लिए, अपनी लाइब्रेरी में सिमD, थ्रेड, और अपवाद हैंडलिंग का इस्तेमाल करना है. उनका ब्राउज़र सहायता इस तरह है:

चुनी गई सुविधाओं के लिए ब्राउज़र की सुविधा दिखाने वाली टेबल.
webassembly.org/roadmap पर यह सुविधा टेबल देखें.

ब्राउज़र को इन समानता रखने वाले लोगों के ग्रुप में बांटा जा सकता है, ताकि हर उपयोगकर्ता को बेहतर अनुभव मिल सके:

  • Chrome पर काम करने वाले ब्राउज़र: Threads, सिम्ड मोड, और अपवाद को मैनेज करना, सभी पर काम करता है.
  • Firefox: Thread और SIMD का इस्तेमाल किया जा सकता है, लेकिन अपवाद को हैंडल नहीं किया जा सकता.
  • Safari: थ्रेड काम करते हैं, सिमडी और अपवाद हैंडलिंग नहीं.
  • अन्य ब्राउज़र: मान लें कि सिर्फ़ बेसलाइन 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

सी++ कोड खुद भी #ifdef __EMSCRIPTEN_PTHREADS__ और #ifdef __SSE2__ का इस्तेमाल कर सकता है. ऐसा करने से, कंपाइलेशन के समय एक जैसे फ़ंक्शन के साथ चलने वाले (थ्रेड और सिमडी) लागू करने और सीरियल लागू करने के तरीकों में से किसी एक को चुनने में आसानी होती है. यह ऐसा दिखेगा:

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 ऐप्लिकेशन से सही बंडल लोड करना होगा. ऐसा करने के लिए, सबसे पहले यह पता लगाएं कि मौजूदा ब्राउज़र में कौनसी सुविधाएं काम करती हैं. vasm-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 की नई सुविधाओं का इस्तेमाल करके, कोड बनाने और लोड करने का इकलौता तरीका रहेगा.