Why Google Sheets ported its calculation worker from JavaScript to WasmGC

Google Sheets is one of the first products at Google to use WasmGC on Chrome. The move was announced in 2022, and the Sheets and Chrome teams partnered on standardization, engineering, and tooling to provide real-time feedback on optimizations. This partnership set a precedent for how engineering teams at Google can effectively work with Chrome to have more Google apps running on WasmGC.

The challenge: JavaScript

The Google Sheets calculation engine was originally written in Java and launched in 2006. In the early days of the product, all calculation happened on the server. However, from 2013, the engine has run in the browser using JavaScript. This was originally accomplished through Google Web Toolkit (GWT), and later through Java to Closure JavaScript transpiler (J2CL). The JavaScript calculation engine runs in a Web Worker and communicates with the main thread using a MessageChannel.

Migrating users from the server to the JavaScript version of the calculation engine (and later from GWT to J2CL) was a major undertaking that required careful validation. To ensure that the JavaScript calculation engine produced precisely the same results as the Java version, the Sheets team developed an internal validation mechanism. This mechanism can process a large corpus of sheets and validate that the results are identical between multiple versions of the calculation engine. The Sheets team uses this tool regularly to validate changes to Sheets. But the team didn't just compare the results of those calculations, they also compared the performance between JavaScript on the client and Java on the server. They found that the JavaScript version of the calculation engine was more than three times slower than the Java version.

Why is JavaScript slower than Java?

JavaScript is fast for a loosely-typed, dynamic language. Heavy investment in just-in-time (JIT) compilers (for example, Maglev, Sparkplug, and Turbofan) over the past 15 years has increased JavaScript's performance. However, JavaScript's loose types and dynamic behavior make it challenging for JIT compilers to generate optimal code. This means JavaScript still lags behind languages like Java and C++ for raw throughput. TypeScript adds type safety to JavaScript, but that type information is designed to make development easier, not to provide the sorts of guarantees needed by compilers to generate optimal code. For cases like Google Sheets, where large spreadsheets can take tens of seconds to calculate, JavaScript is fast, but not fast enough.

The Solution: WasmGC

WasmGC is an extension to the existing WebAssembly specification which adds the primitives needed to compile garbage collected languages (such as Java). For example, WasmGC adds instructions for defining types and allocating garbage collected data structures. WasmGC is poised to do for garbage collected languages what Wasm did for C++ (for example, Photoshop or Google Earth), which is to bring them to the web at near native speed. At Google, we believe that WasmGC has the potential to be even more impactful than Wasm because of the popularity of garbage collected languages.

Google Workspace partners with Chrome

The WasmGC MVP draft specification was published in 2019. In late 2020, Google Workspace and Chrome partnered to evaluate WasmGC using the Sheets calculation engine. Workspace's multiplatform team has significant expertise building and optimizing compilers and transpilers. Sheets, a part of Workspace, was identified as an ideal candidate for evaluating WasmGC: it is performance-sensitive and has robust performance and correctness validation mechanisms. Chrome has the V8 team to build and optimize the WasmGC runtime as well as contributors to Binaryen to build ahead-of-time (AOT) optimizations. Between Chrome and Workspace, there's all the expertise needed to build and optimize a WasmGC toolchain, with Google Sheets as an ideal testbed.

The first prototype

By mid 2021, the teams had a working Java to WasmGC compiler. Toward the end of the same year, they had a prototype version of Google Sheets running as WasmGC and doing calculations. Along the way, they hit many challenges. Tooling for profiling and taking heap dumps did not exist and had to be built. The existing implementation relied on many JavaScript libraries for which replacements had to be found or written for WasmGC. Validating the correctness of the Wasm calculation engine was a time-consuming effort due to the experimental nature of the specification, compiler, and new libraries. But Sheets' validation mechanisms were once again extremely helpful. The teams ultimately got it all working, and performance data started coming in early 2022.

Additional optimizations

The initial version of Sheets Wasm showed calculation performance roughly two times slower than JavaScript. However, this isn't a bad result for a new specification, new compiler, and several new libraries. From this point, the Sheets team began optimizing. Of the optimizations they found, a few categories emerged:

  • Replicating core optimizations that already existed in the Java Virtual Machine (JVM) and in V8.
  • Using highly optimized browser APIs.
  • Removing JavaScript-specific coding patterns.

Firstly, the Sheets team needed to replicate optimizations which already exist in other toolchains. The best example of this is optimizing virtual method dispatching, which has long been optimized by the JVM and V8, but nothing existed for WasmGC. Implementing speculative inlining and devirtualization—two very common optimizations—sped up calculation time by roughly 40% in Chrome.

Second, there are cases where browser APIs are backed by optimized native implementations that are difficult to compete with using Wasm. Strings and regular expressions are two good examples. Specifically, with regular expressions, the team saw nearly a 100 times speedup of regular expression operations when switching from re2j (compiled to WasmGC) to the RegExp browser API in Chrome, which can compile each regular expression to its own machine code.

Lastly, they found that years of optimizing had caused the codebase to be over-fitted to JavaScript. For example, they had a core data structure in Sheets which was blurring the lines between arrays and maps. This is efficient in JavaScript, which automatically models sparse arrays as maps, but slow on other platforms. So they had to rewrite the code in a more platform-agnostic way. This is another thing the team like about WebAssembly: it makes it easier for multiplatform applications to get good performance on the web. You don't have to bend your whole application to the idiosyncrasies of JavaScript.

The final result

After all these optimizations, the final WasmGC version of Sheets achieves a calculation performance approximately twice as fast as JavaScript, representing a fourfold improvement from the starting point of the initial WasmGC version.

Conclusion

WasmGC is a powerful technology that has the potential to advance the way developers build web applications. Over the coming years, at Google, we hope to see WasmGC advance to support shared memory multithreading and further improve single threaded performance. We encourage all web developers to consider using WasmGC for their next high-performance project. Join us and make the web a faster, smoother place together!

Acknowledgements

Thank you for those who worked on the WasmGC implementation and this case study: 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, and Emanuel Ziegler.