Hacker News、TypeScriptがRust WASMを上回った事例に注目

驚きの結果はlanguage speedではなくdata movementの問題だった

OpenUI の March 13, 2026 engineering note は、openui-lang parser が Rust compiled to WASM から TypeScript へ全面的に移植されたあと、なぜ逆に速くなったのかを説明している。この parser は LLM が出力する custom DSL を React component tree に変換し、streaming chunk ごとに実行される。つまり重要なのは parser 単体の純粋な処理速度ではなく、browser 内での end-to-end latency だった。

チームは pipeline を autocloser -> lexer -> splitter -> parser -> resolver -> mapper -> ParseResult として分解し、どこに時間が消えているかを測定した。結論は、Rust の parsing speed が問題ではなかったということだ。高コストだったのは、毎回 JavaScript と WASM の boundary を越える部分だった。入力 string を WASM memory にコピーし、結果を Rust 側で JSON に serialize し、その JSON string を JS へ戻し、さらに V8 で deserialize する。parser logic 自体が十分速くても、固定の interop tax を毎回支払っていたわけだ。

素直な最適化が失敗した理由

OpenUI は JSON round-trip を減らすため、serde-wasm-bindgen で JavaScript object を直接返す方法も試した。しかし fixture によって 9% から 29% ほど遅くなった。説明は browser engineer にとって示唆的だ。Rust struct を本物の JavaScript object に変えるには、runtime boundary をまたぐ細かい conversion が大量に必要になる。一方、JSON string を 1 回渡す方法なら、Rust は 1 つの環境で serialize でき、V8 は 1 回の最適化された pass で parse できる。

より大きな改善はalgorithmにあった

parser を完全に TypeScript へ移したあと、one-shot parsing はサンプル文書で 2.2 倍から 4.6 倍速くなった。ただし実運用でもっと重要だったのは streaming algorithm の修正だ。naive approach は chunk が来るたびに累積した全文字列を parse し直すため、20-character chunk で届く 1000-character response を、合計約 25,000 character 分の parsing work に膨らませてしまう。OpenUI はこれを statement-level incremental caching に置き換え、末尾の未完成 statement だけを再parseし、完了済み statement は cache に保持するようにした。

公開された full-stream の数値はその差をよく示している。contact-form fixture では total parse cost が 316 microseconds から 122 に低下し、dashboard では 840 から 255 まで下がった。より大きな教訓も明確だ。WASM は media processing や cryptography のような compute-heavy かつ interop の少ない処理では有効だが、streaming AI UI の中で structured text を JavaScript object に頻繁に変換する workload では、むしろ不利になることがある。

出典: OpenUI engineering note. Hacker News discussion: item 47461094.