Google スプレッドシートが計算ワーカーを JavaScript から WasmGC に移植した理由

Google スプレッドシートは、Chrome で WasmGC を使用する Google の最初のプロダクトの一つです。この移行は 2022 年に発表されました。スプレッドシート チームと Chrome チームは、標準化、エンジニアリング、ツールの面で連携し、最適化に関するリアルタイムのフィードバックを提供することができました。このパートナーシップは、Google のエンジニアリング チームが Chrome と効果的に連携して、より多くの Google アプリを WasmGC で実行できるようにするための先例となりました。

課題: JavaScript

Google スプレッドシートの計算エンジンは、もともと Java で記述され、2006 年にリリースされました。サービス初期の頃は、すべての計算がサーバーで行われていました。ただし、2013 年以降、このエンジンは JavaScript を使用してブラウザで実行されています。これは、当初は Google Web Toolkit(GWT)で実現されていましたが、その後は Java to Closure JavaScript トランスパイラ(J2CL)で実現されています。JavaScript 計算エンジンは Web Worker で実行され、MessageChannel を使用してメインスレッドと通信します。

サーバーから JavaScript バージョンの計算エンジンにユーザーを移行する(後に GWT から J2CL に移行する)ことは、慎重な検証を必要とする大規模な作業でした。JavaScript 計算エンジンが Java バージョンとまったく同じ結果を生成するように、スプレッドシート チームは内部検証メカニズムを開発しました。このメカニズムでは、大量のシートを処理し、複数のバージョンの計算エンジンで結果が同じであることを検証できます。スプレッドシート チームは、このツールを定期的に使用してスプレッドシートの変更を検証しています。ただし、チームは計算結果だけでなく、クライアント側の JavaScript とサーバー側の Java のパフォーマンスも比較しました。計算エンジンの JavaScript バージョンは Java バージョンの 3 倍以上遅いことがわかりました。

JavaScript が Java よりも遅いのはなぜですか?

JavaScript は、型が緩い動的言語としては高速です。過去 15 年間にジャストインタイム(JIT)コンパイラ(MaglevSparkplugTurbofan など)に多額の投資が行われ、JavaScript のパフォーマンスが向上しました。ただし、JavaScript の緩い型と動的動作により、JIT コンパイラが最適なコードを生成することは困難です。つまり、JavaScript は、未加工のスループットにおいて、Java や C++ などの言語にまだ遅れをとっています。TypeScript は JavaScript に型の安全性を追加しますが、その型情報は、コンパイラが最適なコードを生成するために必要な保証を提供するためではなく、開発を容易にするために設計されています。Google スプレッドシートのように、大きなスプレッドシートの計算に数十秒かかる場合、JavaScript は高速ですが、十分な速さではありません。

ソリューション: WasmGC

WasmGC は、既存の WebAssembly 仕様の拡張であり、ガベージ コレクション言語(Java など)のコンパイルに必要なプリミティブを追加します。たとえば、WasmGC は、型の定義とガベージ コレクションされたデータ構造の割り当てのための命令を追加します。WasmGC は、Wasm が C++(PhotoshopGoogle Earth など)に対して行ったことを、ガベージ コレクション言語に対して行う準備ができています。つまり、ネイティブに近い速度でウェブに移行することです。Google では、ガベージ コレクション言語の人気が高いため、WasmGC は Wasm よりもさらに大きな影響力を持つ可能性があると考えています。

Google Workspace と Chrome のパートナー

WasmGC MVP ドラフト仕様は 2019 年に公開されました。2020 年後半、Google Workspace と Chrome は提携して、スプレッドシートの計算エンジンを使用して WasmGC を評価しました。Workspace のマルチプラットフォーム チームは、コンパイラとトランスパイラの構築と最適化に豊富な経験を持っています。Workspace の一部であるスプレッドシートは、パフォーマンスに敏感で、堅牢なパフォーマンスと正確性の検証メカニズムがあるため、WasmGC の評価に最適な候補として特定されました。Chrome には、WasmGC ランタイムの構築と最適化を行う V8 チームと、事前(AOT)最適化を構築する Binaryen のコントリビューターがいます。Chrome と Workspace には、WasmGC ツールチェーンの構築と最適化に必要な専門知識がすべて揃っています。Google スプレッドシートは理想的なテストベッドです。

最初のプロトタイプ

2021 年半ばまでに、チームは Java から WasmGC へのコンパイラを完成させました。同年末には、Google スプレッドシートのプロトタイプ バージョンを WasmGC として実行し、計算を実行することができました。途中で多くの課題に直面しました。プロファイリングとヒープダンプの取得用のツールが存在しないため、ビルドする必要がありました。既存の実装では多くの JavaScript ライブラリが使用されていましたが、WasmGC 用に置き換えを探すか、書き換える必要がありました。仕様、コンパイラ、新しいライブラリが試験運用版であるため、Wasm 計算エンジンの正確性を検証するには時間がかかりました。ただし、スプレッドシートの検証メカニズムは、ここでも非常に役立ちました。最終的に、すべての機能が動作し、2022 年初頭からパフォーマンス データの収集が開始されました。

その他の最適化

スプレッドシート Wasm の初期バージョンでは、計算パフォーマンスが JavaScript の約 2 倍遅いことが判明しました。ただし、これは新しい仕様、新しいコンパイラ、いくつかの新しいライブラリにとって悪い結果ではありません。この時点で、スプレッドシート チームは最適化を開始しました。見つかった最適化には、次のカテゴリがあります。

  • Java 仮想マシン(JVM)と V8 にすでに存在するコア最適化を複製する。
  • 高度に最適化されたブラウザ API を使用する。
  • JavaScript 固有のコーディング パターンの削除。

まず、スプレッドシート チームは、他のツールチェーンにすでに存在する最適化を再現する必要がありました。その最たる例が、仮想メソッド ディスパッチの最適化です。これは長い間 JVM と V8 で最適化されてきましたが、WasmGC では行われていませんでした。推測的インライン化デバーチャライゼーション(2 つの非常に一般的な最適化)を実装することで、Chrome の計算時間が約 40% 短縮されました。

2 つ目は、ブラウザ API が最適化されたネイティブ実装に基づいており、Wasm で競合するのが難しい場合です。文字列と正規表現はその好例です。特に正規表現では、re2j(WasmGC にコンパイル)から Chrome の RegExp ブラウザ API に切り替えることで、正規表現オペレーションの速度がほぼ 100 倍になりました。この API では、各正規表現を独自のマシンコードにコンパイルできます。

最後に、長年にわたる最適化により、コードベースが JavaScript に過剰適合していることが判明しました。たとえば、スプレッドシートのコア データ構造では、配列とマップの境界が曖昧になっていました。これは、スパース配列をマップとして自動的にモデル化する JavaScript では効率的ですが、他のプラットフォームでは遅くなります。そのため、よりプラットフォームに依存しない方法でコードを書き直す必要がありました。これは、マルチプラットフォーム アプリケーションがウェブで優れたパフォーマンスを簡単に得ることができるという、WebAssembly のもう 1 つの利点です。JavaScript の独自性にアプリケーション全体を合わせる必要はありません。

最終結果

これらの最適化をすべて行った結果、スプレッドシートの最終的な WasmGC バージョンでは、計算パフォーマンスが JavaScript の約 2 倍に向上し、最初の WasmGC バージョンの開始時点から 4 倍の向上を実現しました。

まとめ

WasmGC は、デベロッパーがウェブ アプリケーションを構築する方法の進歩につながる可能性がある強力なテクノロジーです。Google は、今後数年間にわたって WasmGC を進化させ、共有メモリ マルチスレッド処理をサポートし、シングルスレッドのパフォーマンスをさらに向上させることを目指しています。ウェブ デベロッパーの皆様には、次回高パフォーマンスのプロジェクトを構築する際に、WasmGC の使用を検討することをおすすめします。ウェブをより高速でスムーズな場所にするために、ぜひご協力ください。

謝辞

WasmGC の実装とこのケーススタディに携わった方々(Diwas Adhikary、Matthew Albright、Ksenia Bukina、Julien Dramaix、Asim Fazal、Michael Frederick、Goktug Gokdogan、Janice Gu、Adam Klein、Manos Koukoutos、Jakob Kummerow、Matthias Liedtke、Thomas Lively、Roberto Lublinerman、Vishrut Mehta、Thomas Nattestad、Josh Pearlstein、Joaquim Perotti、Chris Ruenes、Steven Saviano、Derek Schuff、Tim Sears、Michael Thomas、Yuan Tian、Philipp Weis、Mason Wu、Alon Zakai、Emanuel Ziegler)に感謝します。