Por que o app Planilhas Google transferiu o worker de cálculo de JavaScript para o WasmGC?

O Planilhas Google é 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 em padronização, engenharia e ferramentas para fornecer feedback em tempo real sobre as otimizações. Essa parceria foi um precedente para a maneira como as equipes de engenharia do Google podem trabalhar com o Chrome de maneira eficaz para que mais apps do Google sejam executados no WasmGC.

O desafio: JavaScript

O mecanismo de cálculo do Planilhas Google foi originalmente escrito em Java e lançado em 2006. Nos primeiros dias do produto, todo o cálculo era feito no servidor. No entanto, desde 2013, o mecanismo foi executado no navegador usando JavaScript. Originalmente, isso foi feito com o Google Web Toolkit (GWT) e, posteriormente, com o transcompilador Java para Closure JavaScript (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.

A migração de usuários do servidor para a versão JavaScript do mecanismo de cálculo (e mais tarde do GWT para o J2CL) era uma tarefa importante que exigia uma validação cuidadosa. Para garantir que o mecanismo de cálculo JavaScript produzisse exatamente os mesmos resultados que a versão em Java, a equipe do app Planilhas desenvolveu um mecanismo de validação interno. Esse mecanismo pode processar um grande conjunto de planilhas e validar se os resultados são idênticos nas várias versões do mecanismo de cálculo. A equipe do app Planilhas usa essa ferramenta regularmente para validar as mudanças feitas no app. Mas a equipe não apenas comparou os resultados desses cálculos, mas também o desempenho entre JavaScript no cliente e Java no servidor. Eles descobriram que a versão JavaScript do mecanismo de cálculo era três vezes mais lenta do que a versão Java.

Por que o JavaScript é mais lento que o Java?

JavaScript é rápido para uma linguagem dinâmica e com tipos flexíveis. O grande investimento em compiladores just-in-time (JIT) (por exemplo, Maglev, Sparkplug e Turbofan) nos últimos 15 anos aumentou o desempenho do JavaScript. No entanto, os tipos flexíveis e o comportamento dinâmico do JavaScript tornam difícil para os compiladores JIT gerar o código ideal. Isso significa que o JavaScript ainda fica atrás de linguagens como Java e C++ em termos de capacidade 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 oferecer as garantias necessárias aos compiladores para gerar o código ideal. Em casos como Planilhas Google, em que planilhas grandes podem levar dezenas de segundos para serem calculadas, o JavaScript é rápido, mas não o suficiente.

A solução: WasmGC

O WasmGC é uma extensão da especificação WebAssembly (em inglês) que adiciona os primitivos necessários para compilar linguagens coletadas de lixo (como Java). Por exemplo, o WasmGC adiciona instruções para definir tipos e alocar estruturas de dados coletados de lixo. O WasmGC está preparado para lidar com linguagens de coleta de lixo da mesma forma que o Wasm fez com o C++ (por exemplo, Photoshop ou Google Earth), que é trazê-las para a Web quase na velocidade nativa. No Google, acreditamos que o WasmGC tem o potencial de ser ainda mais impactante do que o Wasm devido à popularidade das linguagens coletadas de lixo.

Parceiros do Google Workspace com o Chrome

O rascunho de especificação do MVP do WasmGC (em inglês) foi publicado em 2019. No final de 2020, o Google Workspace e o Chrome fizeram uma parceria para avaliar o WasmGC usando o mecanismo de cálculo do app Planilhas. A equipe multiplataforma do Workspace tem experiência significativa na criação e otimização de compiladores e transcompiladores. O Planilhas, que faz 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 do V8 para criar e otimizar o ambiente de execução WasmGC, além de colaboradores do Binaryen para criar otimizações antecipadas (AOT, na sigla em inglês). Entre o Chrome e o Workspace, você tem todo o conhecimento necessário para criar e otimizar um conjunto de ferramentas do WasmGC, usando o app Planilhas Google como um testbed ideal.

O primeiro protótipo

Em meados de 2021, as equipes tinham um compilador Java para WasmGC em funcionamento. No final do mesmo ano, eles tinham uma versão protótipo do Planilhas Google executada como WasmGC e fazendo cálculos. Ao longo do caminho, eles encontraram muitos desafios. Ferramentas para criação de perfil e captura de heap dumps não existiam e precisavam ser criadas. A implementação existente dependia de muitas bibliotecas JavaScript para as quais era necessário encontrar ou escrever substituições para o WasmGC. Validar a exatidão do mecanismo de cálculo Wasm era 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 novamente. As equipes conseguiram fazer tudo funcionar, e os dados de desempenho começaram a ser coletados no início de 2022.

Outras otimizações

A versão inicial do Wasm das Planilhas Google mostrou um desempenho de cálculo cerca de duas vezes mais lento que o do JavaScript. No entanto, isso 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 app Planilhas começou a otimizar. Dentre as otimizações encontradas, algumas categorias surgiram:

  • Replicação de otimizações de núcleo que já existiam na máquina virtual Java (JVM) e no V8.
  • Usar APIs de navegador altamente otimizadas.
  • Remoção de padrões de codificação específicos do JavaScript.

Primeiro, a equipe do app Planilhas precisava replicar as otimizações que já existem em outros conjuntos de ferramentas. O melhor exemplo disso é a otimização do envio de métodos virtuais, que há muito tempo foi otimizado pela JVM e pelo V8, mas nada existia para o WasmGC. A implementação da in-line especulativa e da desvirtualização, duas otimizações muito comuns, acelerou o tempo de cálculo em cerca de 40% no Chrome.

Segundo, há casos em que as APIs do navegador são baseadas em implementações nativas otimizadas que são difíceis de competir com o uso do Wasm. Strings e expressões regulares são dois bons exemplos. Especificamente, com as expressões regulares, a equipe observou um aumento de quase 100 vezes nas operações de expressão regular ao mudar do re2j (compilado para WasmGC) para a API do navegador RegExp no Chrome, que pode compilar cada expressão regular no próprio código de máquina.

Por fim, eles descobriram que anos de otimização fizeram com que a base de código ficasse superajustada para JavaScript. Por exemplo, eles tinham uma estrutura de dados principal no app Planilhas que desfocava as linhas entre as matrizes e os mapas. Isso é eficiente em JavaScript, que modela automaticamente matrizes esparsas como mapas, mas é lento em outras plataformas. Então, eles tiveram que reescrever o código de uma maneira mais independente de plataforma. Essa é outra coisa que a equipe gosta no WebAssembly: ele ajuda aplicativos multiplataforma a ter um bom desempenho na Web. Você não precisa adaptar todo o seu aplicativo às idiossincrasias do JavaScript.

O resultado final

Após todas essas otimizações, a versão final do WasmGC do app Planilhas atinge um desempenho de cálculo aproximadamente duas vezes mais rápido que o JavaScript, o que representa uma melhoria quatro vezes maior em relação ao ponto inicial da versão inicial do WasmGC.

Conclusão

O WasmGC é uma tecnologia poderosa que tem o potencial de melhorar a maneira como os desenvolvedores criam aplicativos da Web. Nos próximos anos, no Google, esperamos que o WasmGC seja compatível com a multissegmentação de memória compartilhada (em inglês) e melhore ainda mais o desempenho de uma linha de execução única. Incentivamos todos os desenvolvedores Web a usar o WasmGC no próximo projeto de alto desempenho. Junte-se a nós e ajude a tornar a Web um lugar mais rápido e fácil.

Agradecimentos

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.