為何 Google 試算表將其計算工作站從 JavaScript 移植到 WasmGC

Google 試算表是 Google 在 Chrome 上使用 WasmGC 的首批產品之一。這項異動於 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 版本慢了三倍以上。

為什麼 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 的跨平台團隊擁有豐富的專業知識,可建構及最佳化編譯器和轉譯器。我們認為,工作平台的一部分「試算表」是評估 WasmGC 的理想候選項目,因為它對效能敏感,且具備強大的效能和正確性驗證機制。Chrome 有 V8 團隊,負責建構及最佳化 WasmGC 執行階段,以及 Binaryen 的貢獻者,以便建構提前最佳化 (AOT) 最佳化功能。Chrome 和 Workspace 之間提供建構及最佳化 WasmGC 工具鍊所需的所有專業知識,Google 試算表則是理想的測試平台。

第一個原型

截至 2021 年中旬,團隊已完成可用的 Java 到 WasmGC 編譯器。同年年底,他們就已開發出以 WasmGC 執行及進行計算的 Google 試算表原型版本。過程中,他們遇到許多挑戰。用於剖析及擷取堆積傾印的工具不存在,因此必須建構。現有的實作方式仰賴許多 JavaScript 程式庫,必須為 WasmGC 尋找或編寫替代程式庫。由於規格、編譯器和新程式庫屬於實驗性質,因此驗證 Wasm 計算引擎的正確性是一項費時的工作。不過,試算表的驗證機制再次發揮了極大的作用。團隊最終解決了所有問題,並在 2022 年初開始提供成效資料。

其他最佳化

初始版本的 Google 試算表 Wasm 計算效能大約比 JavaScript 慢兩倍。不過,對於新規格、新編譯器和幾個新程式庫來說,這並非不錯的結果。從那時起,試算表團隊開始進行最佳化調整。他們發現的最佳化項目包括:

  • 複製 Java 虛擬機器 (JVM) 和 V8 中已存在的核心最佳化功能。
  • 使用經過高度最佳化的瀏覽器 API。
  • 移除 JavaScript 專屬的程式設計模式。

首先,試算表團隊需要複製其他工具鍊中已存在的最佳化功能。最佳範例是最佳化虛擬方法調度,這項工作早已由 JVM 和 V8 完成,但 WasmGC 尚未進行。實作推測內嵌去虛擬化這兩項非常常見的最佳化功能,可在 Chrome 中將計算時間加快約 40%。

其次,在某些情況下,瀏覽器 API 會由經過最佳化的原生實作項目支援,而這些項目很難與 Wasm 競爭。字串和規則運算式就是兩個很好的例子。具體來說,在使用規則運算式時,團隊發現從 re2j (編譯為 WasmGC) 切換至 Chrome 中的 RegExp 瀏覽器 API 後,規則運算式作業速度提升了近 100 倍,因為 RegExp 可以將每個規則運算式編譯為各自的機器碼。

最後,他們發現多年的最佳化作業導致程式碼庫過度適應 JavaScript。舉例來說,他們在試算表中使用了核心資料結構,導致陣列和地圖之間的界線模糊不清。這在 JavaScript 中相當有效率,因為 JavaScript 會自動將稀疏陣列模擬為地圖,但在其他平台上速度較慢。因此,他們必須以更不受平台限制的方式重寫程式碼。這是團隊喜歡 WebAssembly 的另一個原因:這項技術可讓多平台應用程式更輕鬆地在網路上獲得良好效能。您不必為了 JavaScript 的特殊性,而改變整個應用程式。

最終結果

經過所有這些最佳化後,最終的 WasmGC 版 Google 試算表可達到兩倍於 JavaScript 的計算速度,相較於最初的 WasmGC 版本,速度提升了四倍。

結論

WasmGC 是一項強大的技術,可協助開發人員改進建構網頁應用程式的方式。在未來幾年,我們希望 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。