Por qué Hojas de cálculo de Google transfirió su trabajador de cálculo de JavaScript a WasmGC

Hojas de cálculo de Google es uno de los primeros productos de Google en usar WasmGC en Chrome. El cambio se anunció en 2022, y los equipos de Hojas de cálculo y Chrome se asociaron en la estandarización, la ingeniería y las herramientas para proporcionar comentarios en tiempo real sobre las optimizaciones. Esta asociación sentó un precedente sobre cómo los equipos de ingeniería de Google pueden trabajar de manera eficaz con Chrome para que se ejecuten más apps de Google en WasmGC.

El desafío: JavaScript

El motor de cálculo de Hojas de cálculo de Google se escribió originalmente en Java y se lanzó en 2006. En los primeros días del producto, todos los cálculos se realizaban en el servidor. Sin embargo, desde 2013, el motor se ejecuta en el navegador con JavaScript. Originalmente, esto se lograba a través de Google Web Toolkit (GWT) y, más tarde, a través del transcompilador de Java a Closure JavaScript (J2CL). El motor de cálculo de JavaScript se ejecuta en un Web Worker y se comunica con el subproceso principal a través de un MessageChannel.

La migración de usuarios del servidor a la versión de JavaScript del motor de cálculo (y, más adelante, de GWT a J2CL) fue una tarea importante que requirió una validación cuidadosa. Para garantizar que el motor de cálculo de JavaScript produjera exactamente los mismos resultados que la versión de Java, el equipo de Hojas de cálculo desarrolló un mecanismo de validación interno. Este mecanismo puede procesar un gran corpus de hojas y validar que los resultados sean idénticos entre varias versiones del motor de cálculo. El equipo de Hojas de cálculo usa esta herramienta con regularidad para validar los cambios en Hojas de cálculo. Sin embargo, el equipo no solo comparó los resultados de esos cálculos, sino que también comparó el rendimiento entre JavaScript en el cliente y Java en el servidor. Descubrieron que la versión de JavaScript del motor de cálculo era más de tres veces más lenta que la versión de Java.

¿Por qué JavaScript es más lento que Java?

JavaScript es rápido para ser un lenguaje dinámico y de escritura flexible. La gran inversión en compiladores justo a tiempo (JIT) (por ejemplo, Maglev, Sparkplug y Turbofan) en los últimos 15 años aumentó el rendimiento de JavaScript. Sin embargo, los tipos flexibles y el comportamiento dinámico de JavaScript dificultan que los compiladores JIT generen código óptimo. Esto significa que JavaScript aún está por detrás de lenguajes como Java y C++ en cuanto a rendimiento sin procesar. TypeScript agrega seguridad de tipos a JavaScript, pero esa información de tipos está diseñada para facilitar el desarrollo, no para proporcionar los tipos de garantías que necesitan los compiladores para generar código óptimo. En casos como Hojas de cálculo de Google, en los que las hojas de cálculo grandes pueden tardar decenas de segundos en calcularse, JavaScript es rápido, pero no lo suficiente.

La solución: WasmGC

WasmGC es una extensión de la especificación existente de WebAssembly que agrega los elementos primitivos necesarios para compilar lenguajes con recolección de basura (como Java). Por ejemplo, WasmGC agrega instrucciones para definir tipos y asignar estructuras de datos recopiladas por el recolector de basura. WasmGC está a punto de hacer por los lenguajes con recolección de basura lo que Wasm hizo por C++ (por ejemplo, Photoshop o Google Earth), que es llevarlos a la Web a una velocidad casi nativa. En Google, creemos que WasmGC tiene el potencial de ser incluso más impactante que Wasm debido a la popularidad de los lenguajes con recolección de basura.

Google Workspace se integra con Chrome

La especificación preliminar del MVP de WasmGC se publicó en 2019. A fines de 2020, Google Workspace y Chrome se asociaron para evaluar WasmGC con el motor de cálculo de Hojas de cálculo. El equipo multiplataforma de Workspace tiene una gran experiencia en la creación y optimización de compiladores y transpiladores. Hojas de cálculo, que forma parte de Workspace, se identificó como un candidato ideal para evaluar WasmGC: es sensible al rendimiento y tiene mecanismos sólidos de validación del rendimiento y la corrección. Chrome cuenta con el equipo de V8 para compilar y optimizar el tiempo de ejecución de WasmGC, así como con colaboradores de Binaryen para compilar optimizaciones de compilación anticipada (AOT). Entre Chrome y Workspace, se cuenta con toda la experiencia necesaria para compilar y optimizar una cadena de herramientas de WasmGC, con Hojas de cálculo de Google como banco de pruebas ideal.

El primer prototipo

A mediados de 2021, los equipos tenían un compilador de Java a WasmGC en funcionamiento. Hacia fines de ese mismo año, tenían una versión prototipo de Hojas de cálculo de Google que se ejecutaba como WasmGC y realizaba cálculos. En el camino, se enfrentan a muchos desafíos. No existían herramientas para generar perfiles y tomar volcados del montón, por lo que debieron crearse. La implementación existente se basaba en muchas bibliotecas de JavaScript para las que se debían encontrar o escribir reemplazos para WasmGC. Validar la exactitud del motor de cálculo de Wasm fue una tarea que consumió mucho tiempo debido a la naturaleza experimental de la especificación, el compilador y las bibliotecas nuevas. Sin embargo, los mecanismos de validación de Hojas de cálculo volvieron a ser extremadamente útiles. Finalmente, los equipos lograron que todo funcionara y los datos de rendimiento comenzaron a llegar a principios de 2022.

Optimizaciones adicionales

La versión inicial de Hojas de cálculo de Wasm mostró un rendimiento de cálculo aproximadamente dos veces más lento que JavaScript. Sin embargo, este no es un mal resultado para una nueva especificación, un nuevo compilador y varias bibliotecas nuevas. A partir de este punto, el equipo de Hojas de cálculo comenzó a realizar optimizaciones. De las optimizaciones que encontraron, surgieron algunas categorías:

  • Se replicaron las optimizaciones principales que ya existían en la máquina virtual de Java (JVM) y en V8.
  • Usamos APIs del navegador altamente optimizadas.
  • Se quitaron los patrones de codificación específicos de JavaScript.

En primer lugar, el equipo de Hojas de cálculo necesitaba replicar las optimizaciones que ya existen en otras cadenas de herramientas. El mejor ejemplo de esto es la optimización del envío de métodos virtuales, que la JVM y V8 optimizaron durante mucho tiempo, pero no existía nada para WasmGC. La implementación de la inserción especulativa y la devirtualización, dos optimizaciones muy comunes, aceleró el tiempo de cálculo en aproximadamente un 40% en Chrome.

En segundo lugar, hay casos en los que las APIs del navegador se basan en implementaciones nativas optimizadas con las que es difícil competir usando Wasm. Las cadenas y las expresiones regulares son dos buenos ejemplos. Específicamente, con las expresiones regulares, el equipo observó una aceleración de casi 100 veces en las operaciones de expresiones regulares cuando cambió de re2j (compilado en WasmGC) a la API del navegador RegExp en Chrome, que puede compilar cada expresión regular en su propio código de máquina.

Por último, descubrieron que los años de optimización habían provocado que la base de código se ajustara demasiado a JavaScript. Por ejemplo, tenían una estructura de datos principal en Hojas de cálculo que desdibujaba las líneas entre los arrays y los mapas. Esto es eficiente en JavaScript, que modela automáticamente los arrays dispersos como mapas, pero es lento en otras plataformas. Por lo tanto, debieron volver a escribir el código de una manera más independiente de la plataforma. Esto es otro aspecto que le gusta al equipo de WebAssembly: facilita que las aplicaciones multiplataforma tengan un buen rendimiento en la Web. No tienes que adaptar toda tu aplicación a las peculiaridades de JavaScript.

El resultado final

Después de todas estas optimizaciones, la versión final de WasmGC de Hojas de cálculo logra un rendimiento de cálculo aproximadamente dos veces más rápido que JavaScript, lo que representa una mejora de cuatro veces desde el punto de partida de la versión inicial de WasmGC.

Conclusión

WasmGC es una tecnología potente que tiene el potencial de mejorar la forma en que los desarrolladores compilan aplicaciones web. En los próximos años, en Google, esperamos que WasmGC avance para admitir el multihilo de memoria compartida y mejorar aún más el rendimiento de un solo subproceso. Recomendamos a todos los desarrolladores web que consideren usar WasmGC para su próximo proyecto de alto rendimiento. Únete a nosotros y hagamos que la Web sea un lugar más rápido y fluido.

Agradecimientos

Gracias a quienes trabajaron en la implementación de WasmGC y en este caso de estudio: 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 y Emanuel Ziegler.