WebAssembly が効く場面は、宣伝よりずっと少ない

WASM の利得は重い計算、まとまったデータ、少ない境界越えが揃ったときに出ます。O(n) の JavaScript ループを書き直しても、遅い読み込みと追いにくいスタックが残るだけです。

WebAssembly の売り文句はネイティブに近い速度です。それは正しいのですが、記述しているのは計算が終わったあとの状態で、読み込み、コンパイル、境界越え、データのコピーは省略されています。

3 つの条件が同時に要る

  1. 計算が重い:1 回の呼び出しの中に実際の計算量があり、四則演算数回ではない
  2. まとまったデータ:小さな配列を往復させず、大きな塊を一度に渡す
  3. 呼び出しが少ない:境界越えの回数が計算そのものより一桁少ない

3 つが揃えば WASM は 10 倍以上速くなります。1 つでも欠けると、利得は境界のコストに食われます。

本当に効く一群

C / C++ / Rust の実装が既にあり、それがホットパスにある場合です。画像や音声のコーデック、圧縮(zstd や brotli の高圧縮側)、暗号、物理や幾何の計算、そして決定的なサンドボックスが必要な場面(利用者が投げた式の評価、プラグイン機構)。共通点は、アルゴリズムが複雑で、境界がはっきりし、データが塊であることです。

向かない 3 種類

  • DOM を触るもの:WASM から DOM には届かず、すべて JavaScript 経由になります。1 回の境界越えが処理そのものより高くつきます
  • 小さな文字列処理:正規表現、テンプレート、整形。入出力が小さく、境界のコストが支配的になります
  • 性能のためだけの JavaScript の書き直し:JIT は整数ループやプロパティアクセスを十分に処理します。書き直しで得られないことが多く、必ずスタックトレースが読みにくくなります

このサイトの結論:1 つも使わない

いちばん重い処理は数独の求解、ライフゲームの反復、ハッシュ、画像処理で、どれもミリ秒台です。WASM モジュールを足すと数 MB のダウンロード、コンパイル手順、ブラウザのコンソールでしか追えない呼び出し経路が増え、その代わりに体感できない高速化が手に入ります。

まず測る。ボトルネックが O(n) のループなら、別の言語で書いても O(log n) にはならない。

← 記事一覧に戻る

コメント

…