msgpack-wasm
https://gh-card.dev/repos/tosuke-lab/msgpack-wasm.svg https://github.com/tosuke-lab/msgpack-wasm
WebAssemblyの力でMessagePackのデコード速度を上げようとした実験
結果としては失敗した
Serdeにインスパイアされて、WASM側から以下のような関数を呼び出してJS側でオブジェクトを組み立てている
enterMap
enterArray
addValue
これはMessagePackの構造をある程度模倣しているので、WASM側では特に状態を持たずにパースしてガンガン呼んでいく
後述するキーのキャッシュ以外の状態は持たない
速度が出なかった理由
WASM - JS間の関数呼び出しをTurboFanは最適化してくれない
インライン展開が進まず、ボトルネックになる
JSの処理が依然として重い
文字列のUTF8からUTF16への変換は文字列オブジェクトの生成を伴うため、JS側で行う必要がある
さらに悪いことに文字列はMapのキーとして頻繁に登場する
TextDecoderという機能があり、長い文字列に対してはネイティブコードが呼び出されることにより高速
しかしある程度短い文字列についてはV8のネイティブコード呼び出しの遅さがネックになり、結局JSでデコードする必要がある
これはそこそこ重い処理なので、かなり短い文字列については適当なハッシュマップを用意してキャッシュしている
余談なんですが、これを実装している途中でmsgpack-javascriptにキーキャッシュが実装されて大幅に高速化されたので、高速化に貢献したのかもしれない(本当に?)
教訓
WebAssemblyはJavaScriptと高頻度な関数呼び出しを伴う連携ができるようにはできていない
何か非常に重い処理があって、それを丸投げするみたいな用途じゃないと(速度という側面では)活躍できない
これはV8が速すぎるのもある
実際TurboFanが機能しない状態ではmsgpack-wasmはmsgpack-javascriptを超える性能を記録した
アプリケーションの初期化段階で大量のMessagePackを処理したいという状況では役に立つのかもしれない