Les navigateurs analysent-ils le javascript à chaque chargement de page?

191

Les navigateurs (IE et Firefox) analysent-ils les fichiers javascript liés à chaque actualisation de la page?

Ils peuvent mettre en cache les fichiers, donc je suppose qu'ils n'essaieront pas de les télécharger à chaque fois, mais comme chaque page est essentiellement séparée, je m'attends à ce qu'ils déchirent tout ancien code et le réanalysent.

C'est inefficace, bien que parfaitement compréhensible, mais je me demande si les navigateurs modernes sont assez intelligents pour éviter l'étape d'analyse au sein des sites. Je pense aux cas où un site utilise une bibliothèque javascript, comme ExtJS ou jQuery, etc.

ajreal
la source
4
Mon 2c: Je pense que les avantages en termes de performances de la mise en cache des fichiers Javascript analysés sont trop petits pour que cela soit une optimisation significative.
Itay Maman
2
D'après mes repères, cela pourrait en fait avoir de l'importance. Par exemple, le temps de chargement de jQuery est d'environ 30 ms (sur une machine de bureau rapide), dont 20% analysent uniquement le code dans une représentation exécutable, et le reste l'exécute, c'est-à-dire initialise l'objet jQuery dans ce cas. Si vous êtes sur mobile et que vous utilisez deux ou trois bibliothèques, ce délai peut être pertinent, car l'exécution de JavaScript est bloquante et la page est essentiellement vide jusqu'à ce que chaque script JS soit chargé en mémoire.
djjeck

Réponses:

341

Ce sont les détails que j'ai pu déterrer. Il convient de noter tout d'abord que bien que JavaScript soit généralement considéré comme interprété et exécuté sur une VM, ce n'est pas vraiment le cas avec les interpréteurs modernes, qui ont tendance à compiler la source directement dans le code machine (à l'exception d'IE).


Chrome: moteur V8

V8 a un cache de compilation. Cela stocke le JavaScript compilé à l'aide d'un hachage de la source pour jusqu'à 5 garbage collection. Cela signifie que deux morceaux identiques de code source partageront une entrée de cache en mémoire quelle que soit la manière dont ils ont été inclus. Ce cache n'est pas effacé lorsque les pages sont rechargées.

La source


Mise à jour - 19/03/2015

L'équipe Chrome a publié des détails sur ses nouvelles techniques de streaming et de mise en cache JavaScript .

  1. Streaming de script

Le streaming de scripts optimise l'analyse des fichiers JavaScript. [...]

À partir de la version 41, Chrome analyse les scripts asynchrones et différés sur un thread distinct dès que le téléchargement a commencé. Cela signifie que l'analyse peut se terminer quelques millisecondes seulement après la fin du téléchargement et que les pages se chargent jusqu'à 10% plus rapidement.

  1. Mise en cache du code

Normalement, le moteur V8 compile le JavaScript de la page à chaque visite, le transformant en instructions qu'un processeur comprend. Ce code compilé est ensuite rejeté une fois qu'un utilisateur quitte la page car le code compilé dépend fortement de l'état et du contexte de la machine au moment de la compilation.

Chrome 42 introduit une technique avancée de stockage d'une copie locale du code compilé, de sorte que lorsque l'utilisateur revient à la page, les étapes de téléchargement, d'analyse et de compilation peuvent toutes être ignorées. Sur tous les chargements de pages, cela permet à Chrome d'éviter environ 40% du temps de compilation et d'économiser une précieuse batterie sur les appareils mobiles.


Opéra: moteur Carakan

En pratique, cela signifie que chaque fois qu'un programme de script est sur le point d'être compilé, dont le code source est identique à celui d'un autre programme qui a été récemment compilé, nous réutilisons la sortie précédente du compilateur et sautons complètement l'étape de compilation. Ce cache est assez efficace dans les scénarios de navigation typiques où l'on charge page après page à partir du même site, comme différents articles de presse d'un service de news, car chaque page charge souvent la même bibliothèque de scripts, parfois très volumineuse.

Par conséquent, JavaScript est mis en cache lors des recharges de page, deux requêtes adressées au même script ne donneront pas lieu à une recompilation.

La source


Firefox: moteur SpiderMonkey

SpiderMonkey utilise Nanojitcomme back-end natif, un compilateur JIT. Le processus de compilation du code machine peut être vu ici . En bref, il semble recompiler les scripts au fur et à mesure de leur chargement. Cependant, si nous examinons de plus près les composants internes de, Nanojitnous voyons que le moniteur de niveau supérieur jstracer, qui est utilisé pour suivre la compilation, peut passer en trois étapes lors de la compilation, offrant un avantage pour Nanojit:

L'état initial du moniteur de trace est la surveillance. Cela signifie que spidermonkey interprète le bytecode. Chaque fois que spidermonkey interprète un bytecode de saut en arrière, le moniteur note le nombre de fois où la valeur du compteur de programme (PC) de la cible de saut a été sautée. Ce nombre est appelé le nombre de succès pour le PC. Si le nombre de succès d'un PC particulier atteint une valeur seuil, la cible est considérée comme chaude.

Lorsque le moniteur décide qu'un PC cible est chaud, il regarde dans une table de hachage de fragments pour voir s'il existe un fragment contenant du code natif pour ce PC cible. S'il trouve un tel fragment, il passe en mode exécution. Sinon, il passe en mode d'enregistrement.

Cela signifie que pour les hotfragments de code, le code natif est mis en cache. Cela signifie qu'il n'aura pas besoin d'être recompilé. Il n'est pas précisé si ces sections natives hachées sont conservées entre les actualisations de la page. Mais je suppose qu'ils le sont. Si quelqu'un peut trouver des preuves à l'appui, alors c'est excellent.

EDIT : Il a été souligné que le développeur de Mozilla Boris Zbarsky a déclaré que Gecko ne cache pas encore les scripts compilés . Tiré de cette réponse SO .


Safari: JavaScriptCore / SquirelFish Engine

Je pense que la meilleure réponse pour cette implémentation a déjà été donnée par quelqu'un d'autre .

Nous ne mettons actuellement pas en cache le bytecode (ou le code natif). C'est une
option que nous avons envisagée, cependant, actuellement, la génération de code est une
partie insignifiante du temps d'exécution de JS (<2%), nous ne poursuivons donc pas
cela pour le moment.

Ceci a été écrit par Maciej Stachowiak , le développeur principal de Safari. Je pense donc que nous pouvons considérer cela comme vrai.

Je n'ai pas pu trouver d'autres informations, mais vous pouvez en savoir plus sur les améliorations de vitesse du dernier SquirrelFish Extrememoteur ici , ou parcourir le code source ici si vous vous sentez aventureux.


IE: moteur Chakra

Il n'y a pas d'informations actuelles concernant le moteur JavaScript d'IE9 (Chakra) dans ce champ. Si quelqu'un sait quelque chose, veuillez commenter.

C'est assez non officiel, mais pour les anciennes implémentations de moteur d'IE, Eric Lippert ( un développeur MS de JScript ) déclare dans une réponse de blog ici que:

JScript Classic agit comme un langage compilé en ce sens qu'avant l'exécution d'un programme JScript Classic, nous vérifions entièrement la syntaxe du code, générons un arbre d'analyse complet et générons un bytecode. Nous exécutons ensuite le bytecode via un interpréteur de bytecode. En ce sens, JScript est tout aussi "compilé" que Java. La différence est que JScript ne vous permet pas de conserver ou d'examiner notre bytecode propriétaire . De plus, le bytecode est beaucoup plus élevé que le bytecode JVM - le langage bytecode JScript Classic n'est guère plus qu'une linéarisation de l'arborescence d'analyse, alors que le bytecode JVM est clairement destiné à fonctionner sur une machine de pile de bas niveau.

Cela suggère que le bytecode ne persiste en aucun cas et que le bytecode n'est donc pas mis en cache.

Jivings
la source
10
+1, excellente rédaction. Cependant, concernant Firefox, veuillez consulter cette question StackOverflow où le développeur Mozilla Boris Zbarsky explique que Gecko ne le fait actuellement pas.
cha0site
Merci, j'ai vu cela lors de mes voyages mais je n'ai trouvé aucune autre preuve à l'appui. Je modifierai la réponse avec.
Jivings
1
Notez que ce qui a été dit à propos d'IE a été dit en 2003: la première version du moteur JS d'IE9 était dans IE9 en 2011.
gsnedders
De plus, Opera met en cache le bytecode JS sur plus que de simples recharges. (Le code machine généré n'est cependant pas mis en cache).
gsnedders
2
@Jivings Prenez ce qui précède comme source. (Je fais partie des membres de l'équipe Carakan.)
gsnedders
12

Opera le fait, comme mentionné dans l'autre réponse. ( source )

Firefox (moteur SpiderMonkey) ne cache pas le bytecode. ( source )

WebKit (Safari, Konqueror) ne met pas en cache le bytecode. ( source )

Je ne suis pas sûr d'IE [6/7/8] ou de V8 (Chrome), je pense qu'IE pourrait faire une sorte de cache alors que V8 ne le peut pas. IE est une source fermée donc je ne suis pas sûr, mais dans la V8, il peut ne pas être logique de mettre en cache le code «compilé» car ils compilent directement en code machine.

cha0site
la source
1
IE6–8 ne le fera certainement pas. IE9 pourrait, mais je n'ai aucune preuve de toute façon. Le JS compilé n'est probablement mis en cache nulle part car il est assez souvent volumineux.
gsnedders
@gsnedders: Je ne suis pas sûr que IE8 ne puisse techniquement pas le faire, il semble qu'il se compile trop en bytecode (pas officiel mais proche), donc il n'y a aucune raison technique de ne pas le mettre en cache. IE9 semble ajouter un JIT à compiler en code natif.
cha0site
2
Bytecode est utilisé par IE depuis… pour toujours. Il n'y a rien de nouveau dans IE8. C'est simplement que, étant donné un interprète, les performances de l'interpréteur sont tellement plus lentes que le temps d'analyse que cela n'a aucune importance. IE9 a un moteur JS entièrement nouveau (à partir de zéro), donc rien ne suit entre les deux.
gsnedders
3

Autant que je sache, seul Opera met en cache le JavaScript analysé. Voir la section "Programmes compilés mis en cache" ici .

gsnedders
la source
merci, avez-vous également plus de détails sur d'autres familles de navigateurs?
ajreal
2

Cela ne vaut rien que Google Dart s'attaque explicitement à ce problème via "Snapshots" - le but est d'accélérer le temps d'initialisation et de chargement en chargeant la version préparée du code.

InfoQ a une bonne rédaction @ http://www.infoq.com/articles/google-dart

igrigorik
la source
0

Je pense que la bonne réponse serait «pas toujours». D'après ce que je comprends, le navigateur et le serveur jouent un rôle dans la détermination de ce qui est mis en cache. Si vous avez vraiment besoin de recharger des fichiers à chaque fois, je pense que vous devriez pouvoir le configurer à partir d'Apache (par exemple). Bien sûr, je suppose que le navigateur de l'utilisateur pourrait être configuré pour ignorer ce paramètre, mais c'est probablement peu probable.

J'imagine donc que dans la plupart des cas pratiques, les fichiers javascript eux-mêmes sont mis en cache, mais sont réinterprétés dynamiquement à chaque chargement de la page.

Zachary Murray
la source
0

Le navigateur utilise certainement la mise en cache, mais oui, les navigateurs analysent le JavaScript à chaque actualisation d'une page. Parce que chaque fois qu'une page est chargée par le navigateur, il crée 2 arborescences 1. arbre de contenu et 2. arbre de rendu.

Cet arbre de rendu se compose des informations sur la disposition visuelle des éléments dom. Ainsi, chaque fois qu'une page se charge, le javascript est analysé et tout changement dynamique par le javascript aimera positionner l'élément dom, afficher / masquer l'élément, ajouter / supprimer un élément entraînera le navigateur à recréer l'arborescence de rendu. Mais les broswers modernes comme FF et Chrome le gèrent légèrement différemment, ils ont le concept de rendu incrémental, donc chaque fois qu'il y a des changements dynamiques par les js comme mentionné ci-dessus, cela ne fera que rendre ces éléments et les repeindre à nouveau.

Abhidev
la source