Pular para o conteúdo principal

Lançamento do V8 v8.0

· Leitura de 6 minutos
Leszek Swirski, o oitavo de seu nome

Finalmente chegou. Em cada lançamento do V8, a cada seis semanas quando criamos um branch como parte do nosso processo de lançamento, surge a pergunta sobre o que acontecerá quando o V8 atingir a versão 8. Teremos uma festa? Lançaremos um novo compilador? Pularemos as versões 8 e 9 e permaneceremos eternamente na versão X do V8? Finalmente, após mais de 10 anos de trabalho, em nosso 100º post no blog, temos o prazer de anunciar nosso mais novo branch, V8 versão 8.0 V8, e finalmente podemos responder a essa pergunta:

São correções de bugs e melhorias de desempenho.

Este post fornece uma prévia de alguns dos destaques antecipando o lançamento em coordenação com a versão estável do Chrome 80 em algumas semanas.

Desempenho (tamanho e velocidade)​

Compressão de ponteiros​

Alteramos todos os nossos void * para pv, reduzindo o tamanho dos arquivos fonte em até 66%.

O heap do V8 contém uma grande quantidade de itens, por exemplo, valores de ponto flutuante, caracteres de string, código compilado e valores etiquetados (que representam ponteiros no heap do V8 ou pequenos inteiros). Ao inspecionar o heap, descobrimos que esses valores etiquetados ocupam a maior parte do heap!

Os valores etiquetados têm o mesmo tamanho que o ponteiro do sistema: são 32 bits para arquiteturas de 32 bits e 64 bits para arquiteturas de 64 bits. Assim, ao comparar a versão de 32 bits com a de 64 bits, estamos usando o dobro da memória heap para cada valor etiquetado.

Felizmente para nós, temos um truque na manga. Os bits superiores podem ser sintetizados a partir dos bits inferiores. Então, só precisamos armazenar os bits inferiores únicos no heap, economizando preciosos recursos de memória... para economizar uma média de 40% da memória do heap!

A compressão de ponteiros economiza uma média de 40% de memória.

Ao melhorar a memória, geralmente isso vem com o custo de desempenho. Geralmente. Estamos orgulhosos de anunciar que vimos melhorias no desempenho em sites reais no tempo gasto no V8 e em seu coletor de lixo!

DesktopMóvel
FacebookV8-Total-8%-6%
^^GC-10%-17%
CNNV8-Total-3%-8%
^^GC-14%-20%
Google MapsV8-Total-4%-6%
^^GC-7%-12%

Se a compressão de ponteiros despertou seu interesse, fique atento a um post completo no blog com mais detalhes.

Otimização de funções de ordem superior​

Recentemente removemos uma limitação dentro do pipeline de otimização do TurboFan que impedia otimizações agressivas de funções de ordem superior.

const charCodeAt = Function.prototype.call.bind(String.prototype.charCodeAt);

charCodeAt(string, 8);

Até agora, a chamada para charCodeAt era completamente opaca para o TurboFan, o que levava à geração de uma chamada genérica a uma função definida pelo usuário. Com essa mudança, agora somos capazes de reconhecer que estamos na verdade chamando a função interna String.prototype.charCodeAt e, portanto, podemos acionar todas as outras otimizações que o TurboFan possui para melhorar chamadas a funções internas, o que leva ao mesmo desempenho que:

string.charCodeAt(8);

Essa mudança afeta uma série de outras funções internas, como Function.prototype.apply, Reflect.apply e muitas funções de ordem superior de arrays (ex.: Array.prototype.map).

JavaScript​

Encadeamento opcional​

Ao escrever cadeias de acessos a propriedades, os programadores muitas vezes precisam verificar se os valores intermediários são nulos (isto é, null ou undefined). Uma cadeia sem verificação de erros pode lançar exceções, e uma cadeia com verificação explícita de erros é verbosa e tem a consequência indesejada de verificar todos os valores verdadeiros, em vez de apenas os valores não nulos.

// Versão propensa a erros, pode lançar exceções.
const nameLength = db.user.name.length;

// Menos propensa a erros, mas mais difícil de ler.
let nameLength;
if (db && db.user && db.user.name) nameLength = db.user.name.length;

O encadeamento opcional (?.) permite que programadores escrevam cadeias concisas e robustas de acessos a propriedades que verificam se os valores intermediários são nulos. Se um valor intermediário for nulo, toda a expressão avalia para undefined.

// Ainda verifica erros e é muito mais legível.
const nameLength = db?.user?.name?.length;

Além dos acessos a propriedades estáticas, também são suportados acessos a propriedades dinâmicas e chamadas. Por favor, consulte nosso explicador de recursos para mais detalhes e exemplos.

Coalescência nula​

O operador de coalescência nula ?? é um novo operador binário de curto-circuito para lidar com valores padrão. Atualmente, valores padrão às vezes são tratados com o operador lógico ||, como no exemplo a seguir.

function Component(props) {
const enable = props.enabled || true;
// …
}

O uso de || é indesejável para calcular valores padrão porque a || b avalia para b quando a é um valor falsy. Se props.enabled for explicitamente definido como false, enable ainda será verdadeiro.

Com o operador de coalescência nula, a ?? b avalia para b quando a é nulo ou indefinido (null ou undefined), e caso contrário avalia para a. Este é o comportamento desejado para valores padrão, e reescrever o exemplo usando ?? corrige o problema mencionado acima.

function Component(props) {
const enable = props.enabled ?? true;
// …
}

O operador de coalescência nula e o encadeamento opcional são recursos complementares e funcionam bem juntos. O exemplo pode ser ainda mais ajustado para lidar com o caso em que nenhum argumento props é passado.

function Component(props) {
const enable = props?.enabled ?? true;
// …
}

Por favor, consulte nosso explicador de recursos para mais detalhes e exemplos.

API do V8​

Por favor, use git log branch-heads/7.9..branch-heads/8.0 include/v8.h para obter uma lista das alterações na API.

Os desenvolvedores com um checkout ativo do V8 podem usar git checkout -b 8.0 -t branch-heads/8.0 para experimentar os novos recursos no V8 v8.0. Alternativamente, você pode assinar o canal Beta do Chrome e experimentar os novos recursos em breve.