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

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

課題: JavaScript

Google スプレッドシートの計算エンジンは、もともと Java で記述され、2006 年にリリースされました。このプロダクトの初期には、すべての計算がサーバーで行われていました。しかし、2013 年からは JavaScript を使用してブラウザで実行されています。これはもともと Google Web Toolkit(GWT)で実現されていましたが、その後 Java から 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 へのコンパイラを完成させました。同年後半には、WasmGC として実行され、計算を行う Google スプレッドシートのプロトタイプ バージョンが完成しました。その過程で、多くの課題に直面しました。プロファイリングとヒープダンプの取得のためのツールが存在しなかったため、構築する必要がありました。既存の実装は多くの 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 つの理由です。WebAssembly を使用すると、マルチプラットフォーム アプリケーションでウェブ上で優れたパフォーマンスを簡単に実現できます。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 氏に感謝いたします。