• Rust में लिखा गया WASM parser संरचनात्मक रूप से तेज़ है, लेकिन JS-WASM boundary पर data copy और serialization overhead performance bottleneck के रूप में सामने आया
  • serde-wasm-bindgen के जरिए direct object return करना JSON serialization की तुलना में 9~29% धीमा था, क्योंकि runtime के बीच fine-grained conversion cost लगती है
  • पूरे pipeline को TypeScript में port करने पर उसी architecture में single-call performance 2.2~4.6 गुना तेज़ मिली
  • streaming processing में sentence-level caching के जरिए O(N²)→O(N) सुधार से कुल processing speed 2.6~3.3 गुना तेज़ हुई
  • नतीजतन, WASM compute-intensive और low-frequency calls के लिए उपयुक्त है, जबकि JS object parsing या बार-बार call होने वाले functions के लिए उपयुक्त नहीं है

Rust WASM parser की संरचना और सीमाएँ

  • openui-lang parser एक 6-stage pipeline से बना है, जो LLM द्वारा generated DSL को React component tree में बदलता है
    • stages: autocloser → lexer → splitter → parser → resolver → mapper → ParseResult
    • हर stage tokenization, syntax analysis, variable resolution, AST transformation आदि करता है
  • Rust code खुद तेज़ है, लेकिन JS↔WASM के बीच string copy, JSON serialization, और deserialization हर call पर होती है
    • input string copy (JS→WASM), Rust के अंदर parsing, result JSON serialization, JSON copy (WASM→JS), JS में deserialization
  • इस boundary overhead ने कुल performance को dominate किया; Rust की compute speed bottleneck नहीं थी

serde-wasm-bindgen का प्रयास और विफलता

  • JSON serialization से बचने के लिए Rust struct को सीधे JS object के रूप में लौटाने वाले serde-wasm-bindgen का उपयोग किया गया
  • लेकिन 30% slowdown देखा गया
    • Rust struct memory को JS सीधे नहीं पढ़ सकता, और runtimes के बीच memory layout अलग होने से field-level conversion ज़रूरी होती है
    • इसके विपरीत JSON serialization में Rust के अंदर एक बार string बनती है, फिर JS में optimized JSON.parse से उसे process किया जाता है
  • benchmark परिणाम
    Fixture JSON round-trip serde-wasm-bindgen बदलाव
    simple-table 20.5µs 22.5µs -9%
    contact-form 61.4µs 79.4µs -29%
    dashboard 57.9µs 74.0µs -28%

TypeScript में बदलाव और performance improvement

  • उसी 6-stage structure को पूरी तरह TypeScript में port किया गया, WASM boundary हटाई गई और सीधे V8 heap के भीतर execution किया गया
  • single-call benchmark परिणाम
    Fixture TypeScript WASM speedup
    simple-table 9.3µs 20.5µs 2.2 गुना
    contact-form 13.4µs 61.4µs 4.6 गुना
    dashboard 19.4µs 57.9µs 3.0 गुना
  • सिर्फ WASM हटाने से ही प्रति call cost काफ़ी कम हो गई, लेकिन streaming structure की inefficiency अभी भी बनी रही

streaming parsing की O(N²) समस्या और सुधार

  • जब LLM output कई chunks में आती है, तो हर बार पूरे accumulated string को फिर से parse करने की वजह से O(N²) inefficiency होती है
    • उदाहरण: 1000-character document को 20-character के 50 parses में process करना → कुल 25,000 characters process होते हैं
  • समाधान के रूप में sentence-level incremental caching लागू की गई
    • पूरी हो चुकी sentences को cache किया गया, और सिर्फ चल रही sentence को re-parse किया गया
    • cached AST और नई AST को merge करके result लौटाया गया
  • पूरे stream के benchmark
    Fixture naive TS incremental TS speedup
    simple-table 69µs 77µs नहीं
    contact-form 316µs 122µs 2.6 गुना
    dashboard 840µs 255µs 3.3 गुना
  • जितनी ज़्यादा sentences होंगी, caching का असर उतना बड़ा होगा, और कुल throughput linear रूप से सुधरेगा

WASM उपयोग से मिले सबक

  • उपयुक्त स्थितियाँ
    • compute-intensive और कम interaction वाले tasks: image/video processing, cryptography, physics simulation, audio codec आदि
    • मौजूदा native libraries का port: SQLite, OpenCV, libpng आदि
  • अनुपयुक्त स्थितियाँ
    • JS objects में structured text parsing: यहाँ serialization cost हावी हो जाती है
    • छोटे input पर बार-बार call होने वाले functions: यहाँ boundary cost compute से बड़ी होती है
  • मुख्य सबक
    1. bottleneck कहाँ है, यह profile करने के बाद ही language चुननी चाहिए
    2. serde-wasm-bindgen के जरिए direct object transfer और महँगा पड़ता है
    3. algorithmic complexity सुधारना, language switch से भी ज़्यादा असरदार हो सकता है
    4. WASM और JS heap share नहीं करते, इसलिए conversion cost हमेशा रहेगी

अंतिम परिणाम: TypeScript migration और incremental caching से प्रति call 2.2~4.6 गुना, और पूरे stream में 2.6~3.3 गुना performance improvement हासिल हुआ

अभी कोई टिप्पणी नहीं है.

अभी कोई टिप्पणी नहीं है.