10 pontos por GN⁺ 2025-08-05 | Ainda não há comentários. | Compartilhar no WhatsApp
  • No motor V8, a performance da função JSON.stringify foi aumentada em mais de 2x, melhorando a velocidade de serialização de dados
  • Foi introduzido um caminho de otimização para objetos sem efeitos colaterais, omitindo várias verificações defensivas e trazendo grande ganho de velocidade para objetos de dados comuns
  • No processamento de strings, foram aplicados métodos avançados do ponto de vista de hardware e memória, como distinção entre 1 byte/2 bytes, uso de SIMD e mudança na estrutura de buffers temporários
  • No processo de conversão de números, o algoritmo Grisu3 foi substituído por Dragonbox, abrindo caminho para conversões mais rápidas em chamadas de Number.toString() como um todo
  • Em alguns argumentos e formatos, o processamento volta ao caminho normal de serialização, mas na maioria dos cenários de desenvolvimento web o efeito da otimização é aproveitado automaticamente

Visão geral

  • JSON.stringify é a função central para converter dados em string no JavaScript
  • Melhorar a performance dessa função também impacta positivamente tarefas muito importantes na web, como requisições de rede e salvamento no localStorage
  • Com a engenharia mais recente do V8, a velocidade desse recurso foi mais que dobrada, e as principais estratégias de otimização são apresentadas em detalhe

Fast Path sem efeitos colaterais

  • O núcleo da otimização é aplicar um caminho rápido de serialização que só pode ser usado em situações sem efeitos colaterais (side effects)
  • Nessas situações, em vez de recursão, os objetos são percorridos com uma estrutura iterativa, o que elimina a necessidade de verificação de stack overflow e permite tentar serializar objetos mais profundos
  • Quando o objeto de dados é simples, o V8 usa esse Fast Path no lugar da lógica geral mais lenta, omitindo muitas verificações e aumentando a velocidade

Tratamento de diferentes representações de strings

  • O V8 armazena strings de forma diferente conforme sejam caracteres de 1 byte/2 bytes (ASCII/não ASCII); se houver ao menos um caractere não ASCII, tudo passa a ser tratado em 2 bytes
  • Para melhorar a performance da serialização, são compiladas versões separadas do algoritmo para cada tipo de string
  • Como durante o processamento é preciso verificar o tipo da instância da string, quando uma string de 2 bytes é detectada, o serializador apropriado de 2 bytes assume o estado
  • Com isso, praticamente não há sobrecarga na troca de caminho por codificação de string
  • O resultado final é produzido criando buffers separados de 1 byte e 2 bytes, que são simplesmente combinados no final

Otimização da serialização de strings com SIMD

  • Strings JavaScript podem conter caracteres que precisam ser escapados durante a serialização em JSON
  • Strings longas são verificadas vários bytes de uma vez com instruções de hardware SIMD (como ARM64 Neon)
  • Strings curtas usam a abordagem SWAR, processando vários caracteres simultaneamente com operações de bits em registradores de uso geral
  • Em qualquer dos métodos, na maioria dos casos é possível copiar a string inteira rapidamente sem transformações relevantes

Adição da Express Lane (caminho ultrarrápido)

  • Mesmo dentro do Fast Path, foi criada uma Express Lane para permitir serializar apenas copiando chaves, sem trabalho repetitivo como verificação de propriedades
  • Usando a flag de hidden class do objeto, quando as chaves não têm Symbol, todas são enumerable e já foram serializadas sem necessidade de escape, o objeto é marcado como fast-json-iterable
  • Ao serializar outros objetos com a mesma hidden class, a cópia das chaves é feita imediatamente, sem verificações adicionais
  • Essa técnica também é aplicada em JSON.parse para comparação rápida de chaves

Algoritmo double-to-string mais rápido

  • O processo de converter números em string também é frequente e complexo
  • O algoritmo Grisu3 existente foi substituído por Dragonbox, gerando ganho de performance em chamadas de Number.prototype.toString() como um todo

Otimização da estrutura de buffers temporários

  • Ao montar strings, antes era usado um buffer contínuo único, o que causava a sobrecarga de copiar tudo novamente sempre que o espaço acabava
  • O novo método usa uma estrutura de buffer segmentado, conectando vários buffers menores conforme necessário
  • Assim, quando falta espaço, basta alocar um novo buffer, sem necessidade de copiar tudo

Limitações

  • O Fast Path funciona apenas para serialização de dados simples
  • Se as condições abaixo não forem atendidas, o caminho normal é usado
    • Não é possível usar os argumentos replacer ou space (sem Pretty-Print ou transformação)
    • Deve ser um objeto simples, sem método customizado toJSON
    • Se houver propriedades baseadas em índice, o processamento muda para o caminho lento
    • Strings especiais como ConsString não são tratadas
  • Para a maioria dos usos comuns, como serialização de dados, geração de respostas de API e cache de configurações, o efeito da otimização é aplicado automaticamente

Conclusão

  • Ao reorganizar a abordagem em toda a função JSON.stringify, do design básico ao tratamento de memória e caracteres, foi alcançado um ganho de mais de 2x de velocidade no benchmark JetStream2
  • Essas melhorias já podem ser percebidas a partir do V8 versão 13.8 (Chrome 138) ou superior

Ainda não há comentários.

Ainda não há comentários.