Google Sheets est l'un des premiers produits Google à utiliser WasmGC sur Chrome. Cette décision a été annoncée en 2022. Les équipes Sheets et Chrome ont collaboré sur la standardisation, l'ingénierie et les outils afin de fournir des commentaires en temps réel sur les optimisations. Ce partenariat a établi un précédent pour la façon dont les équipes d'ingénieurs de Google peuvent travailler efficacement avec Chrome afin de faire fonctionner davantage d'applications Google sur WasmGC.
Le défi: JavaScript
Le moteur de calcul de Google Sheets a été écrit à l'origine en Java et lancé en 2006. Au début du produit, tous les calculs étaient effectués sur le serveur. Toutefois, depuis 2013, le moteur s'exécute dans le navigateur à l'aide de JavaScript. Cela était initialement effectué via Google Web Toolkit (GWT), puis via le transpilateur Java to Closure JavaScript (J2CL). Le moteur de calcul JavaScript s'exécute dans un Web Worker 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 (et plus tard de GWT vers J2CL) a été une tâche de grande envergure qui a nécessité 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 peut traiter un grand corpus de feuilles et 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, mais aussi les performances entre JavaScript côté client et Java côté serveur. Ils ont 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 pour un langage dynamique à typage lâche. Les investissements importants réalisés au cours des 15 dernières années dans les compilateurs juste-à-temps (JIT, Just-In-Time) (Maglev, Sparkplug et Turbofan, par exemple) ont permis d'améliorer les performances de JavaScript. Toutefois, les types souples et le comportement dynamique de JavaScript rendent difficile la génération de code optimal par les compilateurs JIT. Cela signifie que JavaScript est toujours à la traîne par rapport à des langages tels que Java et C++ en termes de débit brut. TypeScript ajoute la sécurité des types à JavaScript, mais ces informations de type sont conçues pour faciliter le développement, et non pour fournir les types de garanties dont les compilateurs ont besoin pour générer du code optimal. Dans des cas comme Google Sheets, où le calcul de grandes feuilles de calcul peut prendre des dizaines de secondes, JavaScript est rapide, mais pas assez.
La solution: WasmGC
WasmGC est une extension de la spécification WebAssembly existante qui ajoute les primitives nécessaires à la compilation de langages avec garbage collection (tels que Java). Par exemple, WasmGC ajoute des instructions pour définir des types et allouer des structures de données collectées par garbage collection. WasmGC est prêt à faire pour les langages avec garbage collection ce que Wasm a fait pour C++ (par exemple, Photoshop ou Google Earth), c'est-à-dire les porter sur le Web à une vitesse proche de la vitesse native. Chez Google, nous pensons que WasmGC peut avoir un impact encore plus important que Wasm en raison de la popularité des langages avec garbage collection.
Google Workspace s'associe à Chrome
La spécification préliminaire du MVP WasmGC a été publiée en 2019. Fin 2020, Google Workspace et Chrome se sont associés pour évaluer WasmGC à l'aide du moteur de calcul Sheets. L'équipe multiplate-forme de Workspace possède une expertise considérable dans la création et l'optimisation de compilateurs et de transcompilateurs. Sheets, qui fait partie de Workspace, a été identifié comme un candidat idéal pour évaluer WasmGC: il est sensible aux performances et dispose de mécanismes de validation robustes des performances et de l'exactitude. L'équipe V8 de Chrome est chargée de compiler et d'optimiser l'environnement d'exécution WasmGC, tandis que les contributeurs de Binaryen sont chargés de compiler des optimisations AOT (Ahead-of-Time). Chrome et Workspace offrent toute l'expertise nécessaire pour créer et optimiser une chaîne d'outils WasmGC, avec Google Sheets comme banc d'essai idéal.
Premier prototype
À la mi-2021, les équipes disposaient d'un compilateur Java vers WasmGC opérationnel. Vers la fin de la même année, une version prototype de Google Sheets fonctionnait en tant que WasmGC et effectuait des calculs. En chemin, il a rencontré de nombreux défis. Les outils de profilage et de création de vidages de tas de mémoire n'existaient pas et ont dû être créés. L'implémentation existante reposait sur de nombreuses bibliothèques JavaScript pour lesquelles des remplacements devaient être trouvés ou écrits pour WasmGC. La validation de l'exactitude du moteur de calcul Wasm a été un effort long et fastidieux 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 ont une nouvelle fois été d'une aide précieuse. Les équipes ont finalement réussi à tout mettre en place, et les données de performances ont commencé à arriver début 2022.
Optimisations supplémentaires
La version initiale de Sheets Wasm affichait 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. L'équipe Sheets a alors commencé à optimiser l'application. Parmi les optimisations identifiées, quelques catégories se sont dégagées:
- Réplication des 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 modèles de codage spécifiques à JavaScript.
Tout d'abord, l'équipe Sheets devait reproduire les optimisations déjà existantes dans d'autres chaînes d'outils. Le meilleur exemple est l'optimisation du déclenchement de méthode virtuel, qui a longtemps été optimisé par la JVM et V8, mais rien n'existait pour WasmGC. L'implémentation de l'inlining spéculatif et de la dévirtualisation (deux optimisations très courantes) a accéléré le temps de calcul d'environ 40% dans Chrome.
Deuxièmement, il existe des cas où les API du navigateur sont prises en charge par des implémentations natives optimisées qui sont difficiles à concurrencer 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, l'équipe a constaté un accélération de près de 100 fois des opérations d'expression régulière lors du passage de re2j (compilé en WasmGC) à l'API de navigateur RegExp
dans Chrome, qui peut compiler chaque expression régulière en son propre code machine.
Enfin, ils ont constaté que des années d'optimisation avaient entraîné une suradaptation du codebase à JavaScript. Par exemple, la structure de données de base dans Sheets brouillait les frontières entre les tableaux et les cartes. Cette méthode est efficace en JavaScript, qui modélise automatiquement les tableaux épars en tant que cartes, mais elle est lente sur d'autres plates-formes. Il a donc dû réécrire le code de manière plus indépendante des plates-formes. C'est un autre point que l'équipe apprécie de WebAssembly: il permet aux applications multiplates-formes d'obtenir plus facilement de bonnes performances sur le Web. Vous n'avez pas besoin d'adapter l'ensemble de votre application aux particularités de JavaScript.
Résultat final
Après toutes ces optimisations, la version finale de WasmGC de Sheets offre des performances de calcul deux fois plus rapides que JavaScript, soit une amélioration de quatre fois par rapport au point de départ de la version initiale de WasmGC.
Conclusion
WasmGC est une technologie puissante qui peut améliorer la façon dont les développeurs créent des applications Web. Au cours des prochaines années, nous espérons que WasmGC évoluera pour prendre en charge le multithreading de mémoire partagée et améliorera encore les performances en thread unique. Nous encourageons tous les développeurs Web à envisager d'utiliser WasmGC pour leur prochain projet hautes performances. Rejoignez-nous pour faire du Web un lieu plus rapide et plus fluide.
Remerciements
Merci à tous ceux qui ont travaillé sur l'implémentation de WasmGC et sur cette étude de cas : Dilip 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, Joachim Perotti, Chris Ruenes, Steven Saviano, Derek Schuff, Tim Sears, Michael Thomas, Yuan Tian, Philipp Weis, Mason Wu, Alon Zakai et Emanuel Ziegler.