10 पॉइंट द्वारा spilist2 2021-10-09 | 2 टिप्पणियां | WhatsApp पर शेयर करें

परिचय

  • जब ब्राउज़र में JS चलाया जाता है, तो ब्राउज़र का JS engine काफ़ी अच्छी तरह tuned होता है, इसलिए execution तेज़ होती है। लेकिन आजकल JS का इस्तेमाल दूसरे environments में भी बहुत होता है। (serverless, gaming console, iOS आदि)

  • WASM ऐसी runtimes में JS को तेज़ी से चलाने में मदद करने वाली तकनीक है।

काम करने का तरीका

  • अगर JS engine मौजूद हो, तो JS code interpreter और JIT compiler आदि के ज़रिए bytecode में बदला जाता है।

  • जिन environments में JS engine नहीं होता, वहाँ JS engine को code के साथ deploy करना पड़ता है। JS engine को WASM module के रूप में deploy करने से उसे कई environments में portable बनाया जा सकता है।

  • JS code, WASM engine के भीतर isolate किए गए JS engine के अंदर चलता है।

  • WASM engine जिस JS engine का उपयोग करता है, वह SpiderMonkey है, और Firefox भी इसी का उपयोग करता है।

  • WASM अपने-आप machine code नहीं बना सकता, इसलिए उसे JS के ज़रिए compilation प्रक्रिया से गुजरना पड़ता है।

  • लेकिन JIT का उपयोग नहीं किया जा सकता, इसलिए सामान्यतः WASM का धीमा होना स्वाभाविक है। तो फिर WASM आख़िर JS execution को “तेज़” कैसे बनाता है?

WASM का उपयोग कहाँ होता है

iOS (या ऐसे environments जहाँ JIT इस्तेमाल नहीं किया जा सकता) में JS का उपयोग

- gaming console, unprivileged iOS app, smart TV आदि में सुरक्षा कारणों से JIT का उपयोग नहीं किया जा सकता।

    (→ इसमें ऐसे कहा गया है मानो JIT compiling में सुरक्षा issue होना स्वाभाविक हो, लेकिन कारण खोजने पर भी मुझे स्पष्ट रूप से समझ नहीं आया।)

- इसलिए ऐसी जगहों पर interpreter का उपयोग करना पड़ता है, लेकिन वास्तव में इन platforms पर चलने वाले apps अक्सर बहुत लंबे समय तक चलते हैं और code की मात्रा भी बड़ी होती है, इसलिए interpreter के कारण होने वाली सुस्ती से बचना बेहतर है।

- तो interpreter की performance गिरावट से बचते हुए JS का उपयोग कैसे किया जाए?

serverless में JS का उपयोग

- serverless environment में JIT तो मौजूद होता है, लेकिन cold start time लंबा होने से latency बढ़ जाती है। (सिर्फ engine load करने में ही कम-से-कम 5 ms लगते हैं)

- cold start time को छिपाने वाली optimization techniques मौजूद हैं, लेकिन network layer बेहतर होने पर (e.g., QUIC) उनका महत्व कम हो जाता है, और कई serverless functions को एक साथ चलाने पर भी ये techniques बहुत कारगर नहीं रहतीं।

- instance reuse के ज़रिए cold start time से बचा जा सकता है, लेकिन इसका मतलब है कि requests के बीच state share होगी, जो security risk बन जाती है।

- इन कारणों से, व्यवहार में कई बार best practices का पालन न करते हुए एक ही serverless function में बहुत कुछ भर दिया जाता है।

- यानी अगर सिर्फ cold start समस्या हल हो जाए, तो उससे बचने के लिए अलग-अलग techniques अपनाने की ज़रूरत नहीं रहेगी और कई समस्याएँ अपने-आप हल हो जाएँगी।
  • WASM, JS को wrap करके isolate करता है, और WASM का अपना code छोटा और सरल होता है, इसलिए उसकी निगरानी करना आसान होता है और security risk भी कम हो जाता है।

JS engine सबसे ज़्यादा समय कहाँ खर्च करता है

initialization phase

- (engine initialization) यह serverless पर लागू होता है। engine को पहले खुद को तैयार करना पड़ता है और built-in functions को environment में जोड़ना पड़ता है। यही serverless के cold start के धीमे होने के कारणों में से एक है।

- (application initialization) functions को bytecode में parse करना, variables के लिए memory allocate करना, variables को values assign करना

runtime phase

- इस बिंदु के बाद throughput कई शर्तों से प्रभावित होता है।

    - which language features are used

    - whether the code behaves predictably from the JS engine’s point of view

    - what sort of data structures are used

    - whether the code runs long enough to benefit from the JS engine’s optimizing compiler

JS engine को तेज़ बनाने का मतलब है initialization और runtime, इन दोनों phases को तेज़ बनाना। अधिक सटीक रूप से कहें तो, initialization में लगने वाला समय घटाना और runtime में throughput, यानी code processing speed, बढ़ाना।

initialization time घटाना

  • WASM, initialization time घटाने के लिए Wizer नाम के pre-initializer का उपयोग करता है। (छोटे apps के आधार पर, JS isolate की तुलना में JS on WASM लगभग 13 गुना तेज़ है)

    • code को deploy करने से पहले build चरण में, pre-initializer सभी JS code को एक बार initialization चरण तक चलाकर देखता है।

    • ऐसा करने पर JS engine की linear memory में JS code bytecode के रूप में store हो जाता है, और memory allocation भी पूरी हो चुकी होती है।

    • फिर इसे जैसा है वैसा copy करके WASM के data section में चिपका दिया जाता है।

  • जब JS engine instantiate होता है, तो वह data section के सभी data तक पहुँच सकता है। अगर किसी खास memory की ज़रूरत हो, तो उसे data section से copy किया जा सकता है। इसलिए start time की ज़रूरत नहीं पड़ती, और इसी वजह से इसे pre-initialization कहा जाता है।

  • अभी data section को JS engine वाले उसी module में जोड़ा जाता है, लेकिन भविष्य में module linking का उपयोग करके data section को अलग module बनाया जाएगा, ताकि कई applications एक ही JS engine को share कर सकें।

  • और वास्तव में यह pre-initialization technique सिर्फ JS engine तक सीमित नहीं है; यह Python, Ruby, Lua जैसे किसी भी runtime पर लागू की जा सकने वाली अवधारणा है।

throughput बढ़ाना

  • अगर JS code सिर्फ थोड़े समय के लिए चलता है, तो वैसे भी वह JIT तक नहीं पहुँचता, इसलिए WASM का throughput ब्राउज़र जैसा ही होगा। लेकिन लंबे समय तक चलने वाले code में JIT के हस्तक्षेप की मौजूदगी या अनुपस्थिति से throughput का अंतर काफ़ी बड़ा हो जाता है।

  • WASM, JIT का उपयोग नहीं कर सकता, इसलिए इसकी जगह AOT(ahead-of-time) compilation का उपयोग किया गया है, और जहाँ संभव हो वहाँ JIT की techniques को भी अपनाया गया है।

  • JIT की optimization techniques में से एक है inline caching। यानी पहले चल चुके code के टुकड़ों को संभालकर रखना और फिर दोबारा उपयोग करना।

  • WASM में JS के अक्सर इस्तेमाल होने वाले patterns को stub के रूप में पहले से बना दिया गया है। उदाहरण के लिए, object property access।

    • सामान्यतः object property access सही ढंग से करने के लिए shape और offset जानकारी चाहिए, लेकिन ये AOT के साथ पहले से ज्ञात नहीं होतीं।

    • लेकिन shape और offset को parameter के रूप में लेकर property access करने वाला stub पहले से बनाया जा सकता है। इस stub code को कई जगह दोबारा उपयोग किया जा सकता है।

  • WASM ऐसे common patterns को सब stub के रूप में पहले से तैयार रखता है। यह इस बात से स्वतंत्र है कि वास्तविक JS code कैसा दिखता है। इससे JS engine को बनाने वाले machine code की मात्रा घटती है, initialization time कम होता है, और cache locality भी बेहतर होती है।

  • यह पाया गया कि सिर्फ 2kb के stub तैयार रखने से वास्तविक JS code के लगभग 95% हिस्से को कवर किया जा सकता है।

  • यह technique ahead-of-time, यानी code की वास्तविक सामग्री जाने बिना (profiling के बिना) optimization करती है, इसलिए अगर profiling और बेहतर हो जाए तो JIT की तरह और भी optimization की गुंजाइश होगी।

    • लेकिन profiling अपने-आप में आसान नहीं है, इसलिए इस दिशा में अभी प्रयास जारी हैं।

2 टिप्पणियां

 
kunggom 2021-10-10

JIT के security issue के बारे में पहले यहाँ पेश की गई MS Edge टीम की ब्लॉग पोस्ट में संबंधित सामग्री का उल्लेख किया गया था। मूल रूप से JIT engine जटिल होता है, इसलिए attack surface बढ़ जाती है, और JIT में performance सुधारने के लिए लागू की जाने वाली speculative optimization जैसी विधियाँ कुछ खास pattern वाले security problems को बार-बार पैदा करने की प्रवृत्ति रखती हैं। इसी वजह से कहा जाता है कि web browser की security flaws में JIT से जुड़ी security flaws का अनुपात काफ़ी ऊँचा है.

https://hi.news.hada.io/topic?id=4771

https://microsoftedge.github.io/edgevr/posts/Super-Duper-Secure-Mode/

https://docs.google.com/spreadsheets/d/…

 
spilist2 2021-10-10

ओह धन्यवाद! मैंने तो असल में GeekNews देखा ही नहीं था