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

O app 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 se uniram para padronizar, desenvolver e criar ferramentas que fornecem feedback em tempo real sobre otimizações. Essa parceria estabeleceu um precedente para que as equipes de engenharia do Google possam trabalhar de forma eficaz com o Chrome para ter mais apps do Google em execução no WasmGC.

O desafio: JavaScript

O mecanismo de cálculo das Planilhas Google 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 feito pelo Google Web Toolkit (GWT) e, mais tarde, pelo transpiler JavaScript Java to Closure (J2CL). O mecanismo de cálculo do 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 depois do GWT para o J2CL) foi uma tarefa importante que exigiu uma validação cuidadosa. Para garantir que o mecanismo de cálculo do JavaScript produzisse exatamente os mesmos resultados da versão Java, a equipe do 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 entre várias versões do mecanismo de cálculo. A equipe do app usa essa ferramenta regularmente para validar as mudanças nas Planilhas. Mas a equipe não comparou apenas os resultados desses cálculos, mas também a performance 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 que a versão em Java.

Por que o JavaScript é mais lento que o Java?

O JavaScript é rápido para uma linguagem dinâmica com tipo fraco. Investimentos pesados em compiladores just-in-time (JIT, na sigla em inglês) (por exemplo, Maglev, Sparkplug e Turbofan) nos últimos 15 anos aumentaram a performance do JavaScript. No entanto, os tipos flexíveis e o comportamento dinâmico do JavaScript dificultam a geração de um código ideal pelos compiladores JIT. Isso significa que o JavaScript ainda está atrás de linguagens como Java e C++ em termos de taxa de transferência bruta. O TypeScript adiciona segurança de tipo ao JavaScript, mas essas informações são projetadas para facilitar o desenvolvimento, não para fornecer os tipos de garantias necessários para que os compiladores gerem o código ideal. Em casos como o das Planilhas Google, em que planilhas grandes podem levar dezenas de segundos para calcular, o JavaScript é rápido, mas não o suficiente.

A solução: WasmGC

O WasmGC é uma extensão da especificação WebAssembly, que adiciona as primitivas necessárias para compilar linguagens com coleta de lixo, como Java. Por exemplo, o WasmGC adiciona instruções para definir tipos e alocar estruturas de dados de coleta de lixo. A WasmGC está pronta para fazer com linguagens de coleta de lixo o que a Wasm fez com C++ (por exemplo, Photoshop ou Google Earth), ou seja, levá-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 dos linguagens de coleta de lixo.

Parceria do Google Workspace com o Chrome

O rascunho da especificação do MVP do WasmGC 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 das Planilhas. A equipe multiplataforma do Workspace tem experiência significativa na criação e otimização de compiladores e transpiladores. O app 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 do WasmGC, além de colaboradores do Binaryen para criar otimizações antes do tempo (AOT). O Chrome e o Workspace têm toda a experiência necessária para criar e otimizar uma cadeia de ferramentas do WasmGC, com o Google Planilhas como um ambiente de teste 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 das Planilhas Google em execução como WasmGC e fazendo cálculos. No caminho, eles enfrentaram muitos desafios. As ferramentas para criar perfis e fazer despejos de heap não existiam e precisavam ser criadas. A implementação atual dependia de muitas bibliotecas JavaScript, para as quais as substituições precisavam ser encontradas ou escritas para WasmGC. Validar a precisão do mecanismo de cálculo Wasm foi um esforço demorado devido à natureza experimental da especificação, do compilador e das novas bibliotecas. Mas os mecanismos de validação das Planilhas foram mais uma vez muito úteis. As equipes finalmente conseguiram fazer tudo funcionar, e os dados de desempenho começaram a chegar no início de 2022.

Outras otimizações

A versão inicial do Wasm das Planilhas mostrava um desempenho de cálculo 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 Planilhas começou a otimizar. Entre as otimizações encontradas, algumas categorias surgiram:

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

Primeiro, a equipe do Planilhas precisava replicar as otimizações que já existem em outras cadeias de ferramentas. O melhor exemplo disso é a otimização do envio de método virtual, que já foi otimizado pela JVM e pelo V8, mas não existia para o WasmGC. A implementação da inlineização especulativa e da desvirtualização, duas otimizações muito comuns, acelerou o tempo de cálculo em cerca de 40% no Chrome.

Em segundo lugar, há casos em que as APIs do navegador são compatíveis com 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 expressões regulares, a equipe observou um aumento 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 o 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 adaptada demais ao JavaScript. Por exemplo, eles tinham uma estrutura de dados principal nas Planilhas que estava confundindo as linhas entre matrizes e mapas. Isso é eficiente no 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 da plataforma. Essa é outra coisa que a equipe gosta no WebAssembly: ele facilita a obtenção de uma boa performance na Web para aplicativos multiplataforma. 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 de quatro vezes em relação ao ponto de partida da versão inicial do WasmGC.

Conclusão

O WasmGC é uma tecnologia poderosa que tem o potencial de melhorar a forma 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 alto desempenho. Junte-se a nós e ajude a tornar a Web mais rápida e fácil de usar.

Agradecimentos

Agradecemos a todos 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.