Pourquoi Google Sheets a transféré son worker de calcul de JavaScript vers WasmGC

Google Sheets est l'un des premiers produits Google à utiliser WasmGC sur Chrome. Cette transition a été annoncée en 2022, et les équipes Sheets et Chrome se sont associées à la normalisation, à l'ingénierie et aux outils pour fournir des commentaires en temps réel sur les optimisations. Ce partenariat a établi un précédent : les équipes d'ingénieurs Google peuvent travailler efficacement avec Chrome pour exécuter davantage d'applications Google sur WasmGC.

Le défi: JavaScript

Le moteur de calcul Google Sheets a été initialement écrit en Java et a été lancé en 2006. Dans les premiers temps d'utilisation du produit, tous les calculs s'effectuaient sur le serveur. Cependant, depuis 2013, le moteur a été exécuté dans le navigateur à l'aide de JavaScript. À l'origine, cette opération a été réalisée à l'aide de Google Web Toolkit (GWT), puis via le transpiler Java pour fermer JavaScript (J2CL). Le moteur de calcul JavaScript s'exécute dans un nœud de calcul Web et communique avec le thread principal à l'aide d'un MessageChannel.

La migration des utilisateurs du serveur vers la version JavaScript du moteur de calcul (puis de GWT vers J2CL) était une tâche de grande envergure qui nécessitait une validation minutieuse. Pour s'assurer que le moteur de calcul JavaScript produisait exactement les mêmes résultats que la version Java, l'équipe Sheets a développé un mécanisme de validation interne. Ce mécanisme permet de traiter un vaste corpus de feuilles et de vérifier que les résultats sont identiques entre plusieurs versions du moteur de calcul. L'équipe Sheets utilise régulièrement cet outil pour valider les modifications apportées à Sheets. Mais l'équipe n'a pas seulement comparé les résultats de ces calculs, elle a également comparé les performances entre JavaScript sur le client et Java sur le serveur. Elle a constaté que la version JavaScript du moteur de calcul était plus de trois fois plus lente que la version Java.

Pourquoi JavaScript est-il plus lent que Java ?

JavaScript est rapide dans un langage dynamique et peu typé. Les investissements importants réalisés au cours des 15 dernières années dans les compilateurs juste-à-temps (JIT) (par exemple, Maglev, Sparkplug et Turbofan) ont permis d'améliorer les performances de JavaScript. Toutefois, en raison des types lâches et du comportement dynamique de JavaScript, il est difficile pour les compilateurs JIT de générer un code optimal. Cela signifie que JavaScript est toujours en retard par rapport aux langages tels que Java et C++ pour le débit brut. TypeScript ajoute la sûreté du typage à JavaScript, mais ces informations de type sont conçues pour faciliter le développement, et non pour fournir les types de garanties nécessaires aux compilateurs pour générer un code optimal. Dans des cas comme Google Sheets, où les feuilles de calcul volumineuses peuvent prendre des dizaines de secondes à calculer, JavaScript est un outil rapide, mais pas assez rapide.

La solution: WasmGC

WasmGC est une extension de la spécification WebAssembly existante qui ajoute les primitives nécessaires à la compilation des langages avec récupération de mémoire (tels que Java). Par exemple, WasmGC ajoute des instructions pour définir des types et allouer les structures de données de récupération de mémoire. Pour les langages de récupération de mémoire, WasmGC devrait agir de la même manière que Wasm pour C++ (par exemple, Photoshop ou Google Earth), qui consiste à les mettre sur le Web à une vitesse presque native. Chez Google, nous pensons que WasmGC a le potentiel d'avoir encore plus d'impact que Wasm en raison de la popularité des langages de récupération de mémoire.

Google Workspace s'associe à Chrome

Le projet de spécification MVP de WasmGC a été publié en 2019. Fin 2020, Google Workspace et Chrome se sont associés pour évaluer WasmGC à l'aide du moteur de calcul Sheets. L'équipe multiplateforme de Workspace possède une expertise considérable en matière de création et d'optimisation des compilateurs et des transpilateurs. Sheets, qui fait partie de Workspace, a été identifié comme le candidat idéal pour évaluer WasmGC: il est sensible aux performances et possède de solides mécanismes de validation des performances et de l'exactitude. Chrome dispose de l'équipe V8 pour créer et optimiser l'environnement d'exécution WasmGC, ainsi que de contributeurs de Binaryen pour réaliser des optimisations anticipées. Chrome et Workspace offrent toute l'expertise nécessaire pour créer et optimiser une chaîne d'outils WasmGC. Google Sheets est l'outil de test idéal.

Le premier prototype

Mi-2021, les équipes disposaient d'un compilateur Java vers WasmGC fonctionnel. Vers la fin de la même année, elle disposait d'une version prototype de Google Sheets fonctionnant sous le nom de WasmGC et effectuant des calculs. En cours de route, elle a rencontré de nombreux défis. Les outils de profilage et de prise d'empreintes de la mémoire n'existaient pas et devaient être créés. L'implémentation existante reposait sur de nombreuses bibliothèques JavaScript pour lesquelles des solutions de remplacement devaient être trouvées ou écrites pour WasmGC. La vérification de l'exactitude du moteur de calcul Wasm demandait beaucoup de temps en raison de la nature expérimentale de la spécification, du compilateur et des nouvelles bibliothèques. Mais les mécanismes de validation de Sheets se sont encore une fois très utiles. Au final, les équipes ont tout mis en œuvre, et les données sur les performances ont commencé à être recueillies début 2022.

Autres optimisations

La version initiale de Sheets Wasm montrait des performances de calcul environ deux fois plus lentes que JavaScript. Toutefois, ce n'est pas un mauvais résultat pour une nouvelle spécification, un nouveau compilateur et plusieurs nouvelles bibliothèques. À ce stade, l'équipe Sheets a commencé à optimiser les données. Parmi les optimisations identifiées, plusieurs catégories sont apparues:

  • Répliquer les optimisations de base qui existaient déjà dans la machine virtuelle Java (JVM) et dans V8.
  • Utilisation d'API de navigateur hautement optimisées
  • Suppression des schémas de codage spécifiques à JavaScript.

Tout d'abord, l'équipe Sheets devait répliquer les optimisations qui existent déjà dans d'autres chaînes d'outils. Le meilleur exemple est l'optimisation de la distribution des méthodes virtuelles, qui a été optimisée depuis longtemps par la JVM et V8, mais qui n'existait pour rien de WasmGC. L'intégration spéculative et la dévirtualisation, deux optimisations très courantes, ont permis d'accélérer le temps de calcul d'environ 40% dans Chrome.

Ensuite, dans certains cas, les API de navigateur s'appuient sur des implémentations natives optimisées, avec lesquelles il est difficile de rivaliser avec Wasm. Les chaînes et les expressions régulières en sont deux bons exemples. Plus précisément, avec les expressions régulières, les opérations liées aux expressions régulières ont été presque 100 fois plus rapides en passant de re2j (compilé à WasmGC) à l'API de navigateur RegExp dans Chrome, qui peut compiler chaque expression régulière dans son propre code machine.

Enfin, l'équipe a constaté que des années d'optimisation avaient entraîné une surapprentissage du codebase avec JavaScript. Par exemple, ils disposaient d'une structure de données de base dans Sheets, qui floutait les lignes entre les tableaux et les cartes. Cette méthode est efficace avec JavaScript, qui modélise automatiquement des tableaux creux en tant que cartes, mais ralentit sur d'autres plates-formes. Ils ont donc dû réécrire le code d'une manière plus indépendante de la plate-forme. C'est une autre chose que l'équipe apprécie dans WebAssembly: elle permet aux applications multiplateformes d'obtenir plus facilement de bonnes performances sur le Web. Vous n'avez pas besoin de lier toute votre application aux particularités de JavaScript.

Le résultat final

Après toutes ces optimisations, la version finale de WasmGC de Sheets atteint des performances de calcul environ deux fois plus rapides que JavaScript, ce qui représente une amélioration quadruplée par rapport au point de départ de la version initiale de WasmGC.

Conclusion

WasmGC est une technologie puissante qui a le potentiel de faire progresser la façon dont les développeurs créent des applications Web. Dans les années à venir, chez Google, nous espérons voir WasmGC progresser pour prendre en charge le multithreading à mémoire partagée et améliorer les performances monothread. Nous encourageons tous les développeurs Web à utiliser WasmGC pour leur prochain projet hautes performances. Rejoignez-nous et aidez-nous à rendre le Web plus rapide et plus fluide.

Remerciements

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.