Os navegadores analisam o javascript em todas as páginas carregadas?

190

Os navegadores (IE e Firefox) analisam arquivos javascript vinculados toda vez que a página é atualizada?

Eles podem armazenar em cache os arquivos, então acho que eles não tentarão baixá-los a cada vez, mas como cada página é essencialmente separada, espero que eles derrubem qualquer código antigo e o analisem novamente.

Isso é ineficiente, embora perfeitamente compreensível, mas eu me pergunto se os navegadores modernos são inteligentes o suficiente para evitar a etapa de análise nos sites. Estou pensando em casos em que um site usa uma biblioteca javascript, como ExtJS ou jQuery, etc.

ajreal
fonte
4
Meu 2c: sinto que os benefícios de desempenho do armazenamento em cache de arquivos Javascript analisados ​​são muito pequenos para que isso seja uma otimização significativa.
Itay Maman
2
Dos meus benchmarks, isso pode realmente importar. Por exemplo, o tempo de carregamento do jQuery é de cerca de 30 ms (em uma máquina de desktop rápida), dos quais 20% estão analisando apenas o código em uma representação executável e o restante está executando, ou seja, inicializando o objeto jQuery nesse caso. Se você estiver no celular e usar duas ou três bibliotecas, esse atraso poderá ser relevante, pois a execução do JavaScript está bloqueando e a página ficará essencialmente em branco até que todo script JS seja carregado na memória.
djjeck

Respostas:

338

Esses são os detalhes que pude descobrir. Vale a pena notar primeiro que, embora o JavaScript geralmente seja considerado interpretado e executado em uma VM, esse não é realmente o caso dos intérpretes modernos, que tendem a compilar a fonte diretamente no código da máquina (com exceção do IE).


Chrome: motor V8

V8 possui um cache de compilação. Isso armazena o JavaScript compilado usando um hash da fonte para até 5 coletas de lixo. Isso significa que duas partes idênticas do código-fonte compartilharão uma entrada de cache na memória, independentemente de como foram incluídas. Esse cache não é limpo quando as páginas são recarregadas.

Fonte


Atualização - 19/03/2015

A equipe do Chrome divulgou detalhes sobre suas novas técnicas para streaming e cache de JavaScript .

  1. Script Streaming

O fluxo de scripts otimiza a análise de arquivos JavaScript. [...]

A partir da versão 41, o Chrome analisa scripts assíncronos e adiados em um thread separado assim que o download é iniciado. Isso significa que a análise pode concluir apenas milissegundos após o término do download e resulta no carregamento de páginas 10% mais rápidas.

  1. Cache de código

Normalmente, o mecanismo V8 compila o JavaScript da página a cada visita, transformando-o em instruções que um processador entende. Esse código compilado é descartado assim que um usuário navega para fora da página, pois o código compilado depende muito do estado e do contexto da máquina no momento da compilação.

O Chrome 42 apresenta uma técnica avançada de armazenamento de uma cópia local do código compilado, para que, quando o usuário retorne à página, as etapas de download, análise e compilação possam ser ignoradas. Em todos os carregamentos de página, isso permite que o Chrome evite cerca de 40% do tempo de compilação e economize bateria preciosa em dispositivos móveis.


Opera: Carakan Engine

Na prática, isso significa que sempre que um programa de script está prestes a ser compilado, cujo código-fonte é idêntico ao de algum outro programa recentemente compilado, reutilizamos a saída anterior do compilador e pulamos completamente a etapa de compilação. Esse cache é bastante eficaz em cenários de navegação típicos, onde se carrega página após página do mesmo site, como diferentes artigos de notícias de um serviço de notícias, pois cada página carrega frequentemente a mesma biblioteca de scripts, às vezes muito grande.

Portanto, o JavaScript é armazenado em cache nas recargas de página, duas solicitações para o mesmo script não resultarão em uma recompilação.

Fonte


Firefox: SpiderMonkey Engine

O SpiderMonkey usa Nanojitcomo backend nativo, um compilador JIT. O processo de compilação do código da máquina pode ser visto aqui . Em resumo, parece recompilar scripts à medida que são carregados. No entanto, se examinarmos mais de perto os internos Nanojit, veremos que o monitor de nível superior jstracer, usado para rastrear a compilação, pode passar por três estágios durante a compilação, proporcionando um benefício para Nanojit:

O estado inicial do monitor de rastreio é o monitoramento. Isso significa que o spidermonkey está interpretando o bytecode. Sempre que o spidermonkey interpreta um bytecode de salto para trás, o monitor anota o número de vezes que o valor do contador de programa (PC) do alvo de salto foi saltado. Esse número é chamado de contagem de ocorrências para o PC. Se a contagem de ocorrências de um PC em particular atingir um valor limite, o alvo será considerado quente.

Quando o monitor decide que um PC de destino está quente, ele procura em uma hashtable de fragmentos para ver se há um fragmento contendo o código nativo desse PC de destino. Se encontrar um fragmento, ele passa para o modo de execução. Caso contrário, ele passa para o modo de gravação.

Isso significa que para hot fragmentos de código, o código nativo é armazenado em cache. Significado que não precisará ser recompilado. Não está claro se essas seções nativas de hash são mantidas entre as atualizações de página. Mas eu diria que eles são. Se alguém puder encontrar evidências de apoio a isso, então excelente.

EDIT : Tem sido apontado que o desenvolvedor Mozilla Boris Zbarsky afirmou que Gecko não cache de scripts compilados ainda . Retirado desta resposta SO .


Safari: JavaScriptCore / SquirelFish Engine

Penso que a melhor resposta para esta implementação já foi dada por outra pessoa .

No momento, não armazenamos em cache o bytecode (ou o código nativo). É uma
opção que consideramos, no entanto, atualmente, a geração de código é uma
parte trivial do tempo de execução do JS (<2%), portanto, não estamos buscando
isso no momento.

Isto foi escrito por Maciej Stachowiak , o principal desenvolvedor do Safari. Então, acho que podemos considerar isso verdade.

Não consegui encontrar nenhuma outra informação, mas você pode ler mais sobre as melhorias de velocidade do SquirrelFish Extrememecanismo mais recente aqui ou procurar o código fonte aqui se estiver se sentindo aventureiro.


IE: Motor de Chakra

Não há informações atuais sobre o JavaScript Engine do IE9 (Chakra) neste campo. Se alguém souber alguma coisa, comente.

Isto é completamente não-oficial, mas para implementações de motores mais velhos do IE, Eric Lippert ( um desenvolvedor de MS de JScript ) afirma em uma resposta do blog aqui que:

O JScript Classic age como uma linguagem compilada no sentido de que, antes de qualquer programa JScript Classic ser executado, verificamos totalmente o código, geramos uma árvore de análise completa e um bytecode. Em seguida, executamos o bytecode através de um interpretador de bytecode. Nesse sentido, o JScript é tão "compilado" quanto o Java. A diferença é que o JScript não permite que você persista ou examine nosso bytecode proprietário . Além disso, o bytecode é de nível muito superior ao bytecode da JVM - a linguagem de bytecode do JScript Classic é pouco mais que uma linearização da árvore de análise, enquanto o bytecode da JVM claramente se destina a operar em uma máquina de pilha de baixo nível.

Isso sugere que o bytecode não persiste de maneira alguma e, portanto, o bytecode não é armazenado em cache.

Jivings
fonte
10
+1, excelente redação. No entanto, em relação ao Firefox, consulte esta pergunta do StackOverflow em que o desenvolvedor Mozilla Boris Zbarsky explica que o Gecko atualmente não faz isso.
cha0site
Obrigado, vi isso em minhas viagens, mas não consegui encontrar nenhuma outra evidência de apoio. Vou editar a resposta com ele.
22412 Jivings
1
Note-se que o que foi dito sobre o IE foi dito em 2003: motor JS primeiro lançamento do IE9 foi no IE9 em 2011.
gsnedders
Além disso, o Opera armazena em cache JS bytecode mais do que apenas recarregar. (No entanto, o código de máquina gerado não é armazenado em cache).
gsnedders
2
@Jivings Tome o que foi dito acima como fonte. (Eu sou uma das pessoas da equipe Carakan.)
gsnedders
12

Opera faz isso, como mencionado na outra resposta. ( fonte )

O Firefox (mecanismo SpiderMonkey) não armazena em cache o bytecode. ( fonte )

O WebKit (Safari, Konqueror) não armazena em cache o bytecode. ( fonte )

Não tenho certeza sobre o IE [6/7/8] ou o V8 (Chrome), acho que o IE pode fazer algum tipo de cache, enquanto o V8 não. O IE é de código fechado, então não tenho certeza, mas na V8 pode não fazer sentido armazenar em cache o código "compilado", pois eles são compilados diretamente no código da máquina.

cha0site
fonte
1
IE6–8 quase certamente não. O IE9 pode, mas não tenho nenhuma evidência. O JS compilado provavelmente não é armazenado em cache em nenhum lugar porque geralmente é bastante grande.
gsnedders
@gsnedders: Não tenho certeza de que o IE8 não possa fazer isso tecnicamente, parece que ele também é compilado por bytecode (não oficial, mas próximo), portanto não há razão técnica para não armazenar isso em cache. O IE9 parece adicionar um JIT para compilar no código nativo.
cha0site
2
O bytecode foi usado pelo IE por ... para sempre. Não é novidade no IE8. Apenas que, dado um intérprete, o desempenho do intérprete é muito mais lento que o tempo de análise, é totalmente irrelevante. O IE9 possui um mecanismo JS totalmente novo (do zero), portanto, nada acontece entre os dois.
gsnedders
3

Tanto quanto sei, apenas o Opera armazena em cache o JavaScript analisado. Consulte a seção "Programas compilados em cache" aqui .

gsnedders
fonte
obrigado, você também tem mais detalhes de outras famílias de navegadores?
314 ajreal
2

Não vale nada que o Google Dart resolva explicitamente esse problema por meio de "Snapshots" - o objetivo é acelerar o tempo de inicialização e carregamento carregando a versão preparada do código.

A InfoQ tem uma boa redação @ http://www.infoq.com/articles/google-dart

igrigorik
fonte
0

Eu acho que a resposta correta seria "nem sempre". Pelo que entendi, o navegador e o servidor desempenham um papel na determinação do que é armazenado em cache. Se você realmente precisa recarregar arquivos sempre, acho que você deve configurá-lo no Apache (por exemplo). Obviamente, suponho que o navegador do usuário possa ser configurado para ignorar essa configuração, mas isso provavelmente é improvável.

Então, eu imagino que, na maioria dos casos práticos, os próprios arquivos javascript são armazenados em cache, mas são dinamicamente reinterpretados cada vez que a página é carregada.

Zachary Murray
fonte
0

O navegador definitivamente faz uso de cache, mas sim, os navegadores analisam o JavaScript toda vez que uma página é atualizada. Porque sempre que uma página é carregada pelo navegador, ela cria duas árvores: 1. Árvore de conteúdo e 2. Árvore de renderização.

Essa árvore de renderização consiste nas informações sobre o layout visual dos elementos dom. Portanto, sempre que uma página é carregada, o javascript é analisado e qualquer alteração dinâmica do javascript é como posicionar o elemento dom, mostrar / ocultar o elemento, adicionar / remover elemento, fará com que o navegador recrie a árvore de renderização. Mas os broswers modernos como FF e chrome lidam com isso de maneira um pouco diferente; eles têm o conceito de renderização incremental; portanto, sempre que houver mudanças dinâmicas pelos js, como mencionado acima, isso fará com que esses elementos sejam renderizados e repintados novamente.

Abhidev
fonte