Fogli Google è uno dei primi prodotti di Google a utilizzare WasmGC su Chrome. Il trasferimento è stato annunciato nel 2022 e i team di Fogli e Chrome hanno collaborato per la standardizzazione, l'ingegneria e gli strumenti per fornire feedback in tempo reale sulle ottimizzazioni. Questa partnership ha creato un precedente su come i team tecnici di Google possono collaborare in modo efficace con Chrome per far funzionare più app Google su WasmGC.
La sfida: JavaScript
Il motore di calcolo di Fogli Google è stato originariamente scritto in Java e lanciato nel 2006. Nei primi tempi del prodotto, tutti i calcoli venivano eseguiti sul server. Tuttavia, dal 2013 il motore viene eseguito nel browser utilizzando JavaScript. Inizialmente, questa operazione veniva eseguita tramite Google Web Toolkit (GWT) e successivamente tramite il transpiler Java to Closure JavaScript (J2CL). Il motore di calcolo JavaScript viene eseguito in un Web Worker e comunica con il thread principale utilizzando un MessageChannel.
La migrazione degli utenti dal server alla versione JavaScript del motore di calcolo (e successivamente da GWT a J2CL) è stata un'impresa importante che ha richiesto un'attenta convalida. Per garantire che il motore di calcolo JavaScript producesse esattamente gli stessi risultati della versione Java, il team di Fogli ha sviluppato un meccanismo di convalida interno. Questo meccanismo può elaborare un corpus di fogli di grandi dimensioni e verificare che i risultati siano identici tra più versioni del motore di calcolo. Il team di Fogli utilizza regolarmente questo strumento per convalidare le modifiche apportate a Fogli. Ma il team non si è limitato a confrontare i risultati di questi calcoli, ma ha anche confrontato il rendimento tra JavaScript sul client e Java sul server. Hanno scoperto che la versione JavaScript del motore di calcolo era più di tre volte più lenta della versione Java.
Perché JavaScript è più lento di Java?
JavaScript è veloce per un linguaggio dinamico e con tipizzazione debole. I forti investimenti in compilatori just-in-time (JIT) (ad esempio Maglev, Sparkplug e Turbofan) negli ultimi 15 anni hanno migliorato le prestazioni di JavaScript. Tuttavia, i tipi flessibili e il comportamento dinamico di JavaScript rendono difficile per i compilatori JIT generare codice ottimale. Ciò significa che JavaScript è ancora in ritardo rispetto a linguaggi come Java e C++ per quanto riguarda la velocità effettiva. TypeScript aggiunge la sicurezza dei tipi a JavaScript, ma queste informazioni sui tipi sono progettate per semplificare lo sviluppo, non per fornire i tipi di garanzie necessarie ai compilatori per generare codice ottimale. Per casi come Google Fogli, in cui i fogli di lavoro di grandi dimensioni possono richiedere decine di secondi per il calcolo, JavaScript è veloce, ma non abbastanza.
La soluzione: WasmGC
WasmGC è un'estensione della specifica WebAssembly esistente che aggiunge le primitive necessarie per compilare linguaggi con garbage collection (come Java). Ad esempio, WasmGC aggiunge istruzioni per definire i tipi e allocare le strutture di dati raccolte come spazzatura. WasmGC è pronto a fare per i linguaggi con garbage collection ciò che Wasm ha fatto per C++ (ad esempio Photoshop o Google Earth), ovvero portarli sul web a una velocità quasi nativa. In Google riteniamo che WasmGC abbia il potenziale per avere un impatto ancora maggiore rispetto a Wasm grazie alla popolarità dei linguaggi con garbage collection.
Google Workspace collabora con Chrome
La bozza della specifica MVP di WasmGC è stata pubblicata nel 2019. Alla fine del 2020, Google Workspace e Chrome hanno collaborato per valutare WasmGC utilizzando il motore di calcolo di Fogli. Il team multipiattaforma di Workspace ha una notevole esperienza nella creazione e nell'ottimizzazione di compilatori e transpiler. Fogli, parte di Workspace, è stato identificato come candidato ideale per la valutazione di WasmGC: è sensibile alle prestazioni e dispone di solidi meccanismi di convalida delle prestazioni e della correttezza. Chrome ha il team V8 per creare e ottimizzare il runtime WasmGC, nonché i collaboratori di Binaryen per creare ottimizzazioni AOT (ahead-of-time). Tra Chrome e Workspace, c'è tutta l'esperienza necessaria per creare e ottimizzare una toolchain WasmGC, con Fogli Google come banco di prova ideale.
Il primo prototipo
Entro la metà del 2021, i team avevano un compilatore Java to WasmGC funzionante. Verso la fine dello stesso anno, avevano una versione prototipo di Fogli Google in esecuzione come WasmGC che eseguiva calcoli. Lungo il percorso, hanno incontrato molte sfide. Gli strumenti per la profilazione e l'acquisizione di dump dell'heap non esistevano e dovevano essere creati. L'implementazione esistente si basava su molte librerie JavaScript per le quali è stato necessario trovare o scrivere sostituzioni per WasmGC. La convalida della correttezza del motore di calcolo Wasm ha richiesto molto tempo a causa della natura sperimentale della specifica, del compilatore e delle nuove librerie. Ma i meccanismi di convalida di Fogli sono stati ancora una volta estremamente utili. Alla fine i team sono riusciti a far funzionare tutto e i dati sul rendimento hanno iniziato ad arrivare all'inizio del 2022.
Altre ottimizzazioni
La versione iniziale di Fogli Wasm ha mostrato prestazioni di calcolo circa due volte più lente rispetto a JavaScript. Tuttavia, non è un risultato negativo per una nuova specifica, un nuovo compilatore e diverse nuove librerie. A questo punto, il team di Fogli ha iniziato l'ottimizzazione. Tra le ottimizzazioni trovate, sono emerse alcune categorie:
- Replica delle ottimizzazioni principali già esistenti nella macchina virtuale Java (JVM) e in V8.
- Utilizzo di API del browser altamente ottimizzate.
- Rimozione di pattern di codifica specifici di JavaScript.
Innanzitutto, il team di Fogli doveva replicare le ottimizzazioni già esistenti in altre toolchain. L'esempio migliore è l'ottimizzazione dell'invio di metodi virtuali, che è stata a lungo ottimizzata da JVM e V8, ma non esisteva nulla per WasmGC. L'implementazione dell'inlining speculativo e della devirtualizzazione, due ottimizzazioni molto comuni, ha accelerato il tempo di calcolo di circa il 40% in Chrome.
In secondo luogo, esistono casi in cui le API del browser sono supportate da implementazioni native ottimizzate con cui è difficile competere utilizzando Wasm. Stringhe ed espressioni regolari sono due buoni esempi. Nello specifico, con le espressioni regolari, il team ha riscontrato un aumento di velocità di quasi 100 volte delle operazioni con le espressioni regolari quando è passato da re2j (compilato in WasmGC) all'API browser RegExp in Chrome, che può compilare ogni espressione regolare nel proprio codice macchina.
Infine, hanno scoperto che anni di ottimizzazione avevano fatto sì che la base di codice fosse eccessivamente adattata a JavaScript. Ad esempio, avevano una struttura di dati principale in Fogli che sfumava i confini tra array e mappe. Questo è efficiente in JavaScript, che modella automaticamente gli array sparsi come mappe, ma lento su altre piattaforme. Quindi hanno dovuto riscrivere il codice in modo più indipendente dalla piattaforma. Questo è un altro aspetto che il team apprezza di WebAssembly: semplifica l'ottenimento di buone prestazioni sul web per le applicazioni multipiattaforma. Non devi adattare l'intera applicazione alle peculiarità di JavaScript.
Il risultato finale
Dopo tutte queste ottimizzazioni, la versione finale di Fogli con WasmGC raggiunge un rendimento di calcolo circa due volte più veloce di JavaScript, il che rappresenta un miglioramento di quattro volte rispetto al punto di partenza della versione iniziale di WasmGC.
Conclusione
WasmGC è una tecnologia potente che ha il potenziale per far progredire il modo in cui gli sviluppatori creano applicazioni web. Nei prossimi anni, in Google speriamo di vedere WasmGC avanzare per supportare il multithreading con memoria condivisa e migliorare ulteriormente le prestazioni a thread singolo. Invitiamo tutti gli sviluppatori web a prendere in considerazione l'utilizzo di WasmGC per il loro prossimo progetto ad alte prestazioni. Unisciti a noi e rendiamo insieme il web un luogo più veloce e fluido.
Ringraziamenti
Grazie a tutti coloro che hanno lavorato all'implementazione di WasmGC e a questo 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 e Emanuel Ziegler.