O Google Planilhas é um dos primeiros produtos do Google a usar o WasmGC no Chrome. A mudança foi anunciada em 2022, e as equipes do Planilhas e do Chrome fizeram uma parceria para padronização, engenharia e ferramentas, oferecendo feedback em tempo real sobre as otimizações. Essa parceria estabeleceu um precedente de como as equipes de engenharia do Google podem trabalhar com o Chrome para ter mais apps do Google executados no WasmGC.
O desafio: JavaScript
O mecanismo de cálculo do Google Sheets foi originalmente escrito em Java e lançado em 2006. No início do produto, todos os cálculos eram feitos no servidor. No entanto, desde 2013, o mecanismo é executado no navegador usando JavaScript. Isso foi originalmente realizado pelo Google Web Toolkit (GWT) e, mais tarde, pelo transpilador Java para JavaScript do Closure (J2CL). O mecanismo de cálculo JavaScript é executado em um Web Worker e se comunica com a linha de execução principal usando um MessageChannel.
Migrar usuários do servidor para a versão JavaScript do mecanismo de cálculo (e depois do GWT para o J2CL) foi uma tarefa importante que exigiu validação cuidadosa. Para garantir que o mecanismo de cálculo em JavaScript produzisse exatamente os mesmos resultados da versão em Java, a equipe do Google Sheets desenvolveu um mecanismo de validação interna. Esse mecanismo pode processar um grande corpus de planilhas e validar se os resultados são idênticos em várias versões do mecanismo de cálculo. A equipe das Planilhas usa essa ferramenta regularmente para validar mudanças nas Planilhas. Mas a equipe não apenas comparou os resultados desses cálculos, como também o desempenho entre JavaScript no cliente e Java no servidor. Eles descobriram que a versão em JavaScript do mecanismo de cálculo era mais de três vezes mais lenta do que a versão em Java.
Por que o JavaScript é mais lento que o Java?
O JavaScript é rápido para uma linguagem dinâmica e de tipagem fraca. O grande investimento em compiladores just-in-time (JIT), como Maglev, Sparkplug e Turbofan, nos últimos 15 anos aumentou a performance do JavaScript. No entanto, os tipos soltos e o comportamento dinâmico do JavaScript dificultam a geração de código ideal pelos compiladores JIT. Isso significa que o JavaScript ainda fica atrás de linguagens como Java e C++ em termos de taxa de transferência bruta. O TypeScript adiciona segurança de tipos ao JavaScript, mas essas informações de tipo são projetadas para facilitar o desenvolvimento, não para fornecer os tipos de garantias necessárias aos compiladores para gerar um código ideal. Em casos como o Google Sheets, em que planilhas grandes podem levar dezenas de segundos para serem calculadas, o JavaScript é rápido, mas não rápido o suficiente.
A solução: WasmGC
O WasmGC é uma extensão da especificação WebAssembly atual que adiciona as primitivas necessárias para compilar linguagens coletadas por lixo (como Java). Por exemplo, o WasmGC adiciona instruções para definir tipos e alocar estruturas de dados coletados como lixo. O WasmGC está prestes a fazer para linguagens coletadas por lixo o que o Wasm fez para C++ (por exemplo, Photoshop ou Google Earth), que é trazê-las para a Web com velocidade quase nativa. No Google, acreditamos que o WasmGC tem o potencial de ser ainda mais impactante do que o Wasm devido à popularidade das linguagens coletadas por lixo.
O Google Workspace faz parceria com o Chrome
O rascunho da especificação do MVP do WasmGC foi publicado em 2019. No fim de 2020, o Google Workspace e o Chrome fizeram uma parceria para avaliar o WasmGC usando o mecanismo de cálculo das Planilhas. A equipe multiplataforma do Workspace tem muita experiência na criação e otimização de compiladores e transpiladores. O Google Sheets, parte do Workspace, foi identificado como um candidato ideal para avaliar o WasmGC: ele é sensível ao desempenho e tem mecanismos robustos de validação de desempenho e correção. O Chrome tem a equipe V8 para criar e otimizar o tempo de execução do WasmGC, além de colaboradores do Binaryen para criar otimizações antecipadas (AOT, na sigla em inglês). Entre o Chrome e o Workspace, há toda a experiência necessária para criar e otimizar uma cadeia de ferramentas WasmGC, com o Google Sheets como um ambiente de teste ideal.
O primeiro protótipo
Até meados de 2021, as equipes tinham um compilador Java para WasmGC funcionando. No final do mesmo ano, eles tinham uma versão protótipo das Planilhas Google executando como WasmGC e fazendo cálculos. Ao longo do caminho, eles enfrentam muitos desafios. Não havia ferramentas para criação de perfis e coleta de despejos de heap, que precisaram ser criadas. A implementação atual dependia de muitas bibliotecas JavaScript para as quais substituições precisavam ser encontradas ou escritas para WasmGC. Validar a correção do mecanismo de cálculo do Wasm foi um esforço demorado devido à natureza experimental da especificação, do compilador e das novas bibliotecas. Mas os mecanismos de validação do Planilhas foram extremamente úteis mais uma vez. As equipes finalmente fizeram tudo funcionar, e os dados de performance começaram a chegar no início de 2022.
Otimizações adicionais
A versão inicial do Wasm das Planilhas mostrou um desempenho de cálculo aproximadamente duas vezes mais lento do que o JavaScript. No entanto, esse não é um resultado ruim para uma nova especificação, um novo compilador e várias novas bibliotecas. A partir desse ponto, a equipe do Google Sheets começou a otimizar. Das otimizações encontradas, surgiram algumas categorias:
- Replicação das otimizações principais que já existiam na máquina virtual Java (JVM) e no V8.
- Usar APIs do navegador altamente otimizadas.
- Remoção de padrões de programação específicos do JavaScript.
Primeiro, a equipe do Google Sheets precisou replicar otimizações que já existem em outras cadeias de ferramentas. O melhor exemplo disso é a otimização do despacho de métodos virtuais, que há muito tempo é otimizado pela JVM e pelo V8, mas não existia para o WasmGC. A implementação de inlining especulativo e devirtualização, duas otimizações muito comuns, acelerou o tempo de cálculo em aproximadamente 40% no Chrome.
Em segundo lugar, há casos em que as APIs do navegador são apoiadas por implementações nativas otimizadas que são difíceis de competir usando Wasm. Strings e expressões regulares são dois bons exemplos. Especificamente, com expressões regulares, a equipe observou uma aceleração de quase 100 vezes nas operações de expressões regulares ao mudar de re2j (compilado para WasmGC) para a API do navegador RegExp no Chrome, que pode compilar cada expressão regular para seu próprio código de máquina.
Por fim, eles descobriram que anos de otimização fizeram com que a base de código fosse ajustada demais ao JavaScript. Por exemplo, eles tinham uma estrutura de dados principal no Planilhas que estava confundindo as linhas entre matrizes e mapas. Isso é eficiente em JavaScript, que modela automaticamente matrizes esparsas como mapas, mas é lento em outras plataformas. Por isso, eles tiveram que reescrever o código de uma forma mais independente de plataforma. Outro aspecto que a equipe gosta no WebAssembly é que ele facilita o bom desempenho de aplicativos multiplataforma na Web. Não é necessário adaptar todo o aplicativo às idiossincrasias do JavaScript.
O resultado final
Depois de todas essas otimizações, a versão final do WasmGC das Planilhas Google alcança uma performance de cálculo aproximadamente duas vezes mais rápida que o JavaScript, representando uma melhoria quatro vezes maior do que o ponto de partida da versão inicial do WasmGC.
Conclusão
O WasmGC é uma tecnologia poderosa que tem o potencial de avançar a maneira como os desenvolvedores criam aplicativos da Web. Nos próximos anos, esperamos que o WasmGC avance para oferecer suporte a multithreading de memória compartilhada e melhorar ainda mais o desempenho de uma única linha de execução. Recomendamos que todos os desenvolvedores da Web considerem usar o WasmGC no próximo projeto de alta performance. Participe e deixe a Web mais rápida e tranquila com a gente!
Agradecimentos
Agradecemos às pessoas que trabalharam na implementação do WasmGC e neste estudo de caso: 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.