Dies sind die Details, die ich ausgraben konnte. Zunächst ist anzumerken, dass JavaScript zwar normalerweise als interpretiert und auf einer VM ausgeführt betrachtet wird, dies jedoch bei modernen Interpreten, die dazu neigen, die Quelle direkt in Maschinencode zu kompilieren (mit Ausnahme des IE), nicht wirklich der Fall ist.
Chrome: V8-Motor
V8 verfügt über einen Kompilierungscache. Hiermit wird kompiliertes JavaScript unter Verwendung eines Hash der Quelle für bis zu 5 Garbage Collections gespeichert. Dies bedeutet, dass zwei identische Teile des Quellcodes einen Cache-Eintrag im Speicher gemeinsam nutzen, unabhängig davon, wie sie enthalten waren. Dieser Cache wird nicht gelöscht, wenn Seiten neu geladen werden.
Quelle
Update - 19/03/2015
Das Chrome-Team hat Details zu seinen neuen Techniken für das Streaming und Caching von JavaScript veröffentlicht .
- Skript-Streaming
Skript-Streaming optimiert das Parsen von JavaScript-Dateien. [...]
Ab Version 41 analysiert Chrome asynchrone und verzögerte Skripte in einem separaten Thread, sobald der Download begonnen hat. Dies bedeutet, dass das Parsen nur Millisekunden nach Abschluss des Downloads abgeschlossen werden kann und das Laden von Seiten um bis zu 10% schneller erfolgt.
- Code-Caching
Normalerweise kompiliert die V8-Engine bei jedem Besuch das JavaScript der Seite und wandelt es in Anweisungen um, die ein Prozessor versteht. Dieser kompilierte Code wird dann verworfen, sobald ein Benutzer von der Seite weg navigiert, da der kompilierte Code zum Zeitpunkt der Kompilierung stark vom Status und Kontext des Computers abhängt.
In Chrome 42 wird eine erweiterte Technik zum Speichern einer lokalen Kopie des kompilierten Codes eingeführt, sodass beim Herunterladen auf die Seite alle Schritte zum Herunterladen, Parsen und Kompilieren übersprungen werden können. Auf diese Weise kann Chrome bei allen Seitenladevorgängen etwa 40% der Kompilierungszeit vermeiden und auf Mobilgeräten wertvollen Akku sparen.
Oper: Carakan-Motor
In der Praxis bedeutet dies, dass wir jedes Mal, wenn ein Skriptprogramm kompiliert werden soll, dessen Quellcode mit dem eines anderen kürzlich kompilierten Programms identisch ist, die vorherige Ausgabe des Compilers wiederverwenden und den Kompilierungsschritt vollständig überspringen. Dieser Cache ist sehr effektiv in typischen Browserszenarien, in denen Seite für Seite von derselben Site geladen wird, z. B. verschiedene Nachrichtenartikel von einem Nachrichtendienst, da jede Seite häufig dieselbe, manchmal sehr große Skriptbibliothek lädt.
Daher wird JavaScript beim erneuten Laden von Seiten zwischengespeichert. Zwei Anforderungen an dasselbe Skript führen nicht zu einer Neukompilierung.
Quelle
Firefox: SpiderMonkey Engine
SpiderMonkey verwendet Nanojit
als natives Backend einen JIT-Compiler. Der Prozess des Kompilierens des Maschinencodes ist hier zu sehen . Kurz gesagt, es scheint , Skripte beim Laden neu zu kompilieren. Wenn wir uns jedoch die Interna von genauer ansehen,Nanojit
sehen wir, dass der übergeordnete Monitor jstracer
, der zum Verfolgen der Kompilierung verwendet wird, während der Kompilierung drei Phasen durchlaufen kann und folgende Vorteile bietet Nanojit
:
Der Ausgangszustand des Trace-Monitors ist die Überwachung. Dies bedeutet, dass Spidermonkey Bytecode interpretiert. Jedes Mal, wenn spidermonkey einen Rückwärtssprung-Bytecode interpretiert, notiert der Monitor, wie oft der Wert des Sprungziel-Programmzählers (PC) gesprungen wurde. Diese Zahl wird als Trefferzahl für den PC bezeichnet. Wenn die Trefferzahl eines bestimmten PCs einen Schwellenwert erreicht, wird das Ziel als heiß angesehen.
Wenn der Monitor feststellt, dass ein Ziel-PC heiß ist, prüft er in einer Hashtabelle mit Fragmenten, ob ein Fragment nativen Code für diesen Ziel-PC enthält. Wenn ein solches Fragment gefunden wird, wechselt es in den Ausführungsmodus. Andernfalls wechselt es in den Aufnahmemodus.
Dies bedeutet, dass für hot
Codefragmente der native Code zwischengespeichert wird. Dies bedeutet, dass dies nicht neu kompiliert werden muss. Es wird nicht klargestellt, dass diese nativen Hash-Abschnitte zwischen den Seitenaktualisierungen beibehalten werden. Aber ich würde annehmen, dass sie es sind. Wenn jemand Belege dafür finden kann, dann ausgezeichnet.
EDIT : Es wurde darauf hingewiesen, dass Mozilla-Entwickler Boris Zbarsky erklärt hat, dass Gecko kompilierte Skripte noch nicht zwischenspeichert . Entnommen aus dieser SO-Antwort .
Safari: JavaScriptCore / SquirelFish Engine
Ich denke, dass die beste Antwort für diese Implementierung bereits von jemand anderem gegeben wurde .
Derzeit wird der Bytecode (oder der native Code) nicht zwischengespeichert. Es ist eine
Option, die wir in Betracht gezogen haben. Derzeit ist die Codegenerierung jedoch ein
trivialer Teil der JS-Ausführungszeit (<2%). Daher verfolgen wir
dies derzeit nicht.
Dies wurde von Maciej Stachowiak , dem Hauptentwickler von Safari, geschrieben. Ich denke, wir können das als wahr ansehen.
Ich konnte keine andere Informationen finden , aber Sie können mehr über die Verbesserungen in der Geschwindigkeit der neuesten lesen SquirrelFish Extreme
Motor hier , sehen Sie den Quellcode hier , wenn Sie etwas Zeit mitbringen.
IE: Chakra-Motor
In diesem Feld gibt es keine aktuellen Informationen zur JavaScript Engine (Chakra) von IE9. Wenn jemand etwas weiß, bitte kommentieren.
Dies ist ziemlich inoffiziell, aber für die älteren Engine-Implementierungen des IE gibt Eric Lippert ( ein MS-Entwickler von JScript ) in einer Blog-Antwort hier Folgendes an :
JScript Classic verhält sich wie eine kompilierte Sprache in dem Sinne, dass wir vor der Ausführung eines JScript Classic-Programms den Code vollständig syntaktisch überprüfen, einen vollständigen Analysebaum generieren und einen Bytecode generieren. Wir führen den Bytecode dann durch einen Bytecode-Interpreter. In diesem Sinne ist JScript genauso "kompiliert" wie Java. Der Unterschied besteht darin, dass Sie mit JScript unseren proprietären Bytecode nicht beibehalten oder überprüfen können . Außerdem ist der Bytecode viel höher als der JVM-Bytecode - die JScript Classic-Bytecode-Sprache ist kaum mehr als eine Linearisierung des Analysebaums, während der JVM-Bytecode eindeutig für den Betrieb auf einem Low-Level-Stack-Computer vorgesehen ist.
Dies deutet darauf hin, dass der Bytecode in keiner Weise bestehen bleibt und der Bytecode daher nicht zwischengespeichert wird.