2010-01-26 11 views
50

Ich bin gerade verwirrt über JavaScript-Engines. Ich weiß, dass V8 eine große Sache war, weil es JavaScript zu nativem Code kompilierte.Javascript Engines Vorteile

Dann begann ich über Mozilla SpiderMonkey zu lesen, was von dem, was ich verstehe, ist in C geschrieben und kann JavaScript zu kompilieren. Wie unterscheidet sich das von V8 und wenn das stimmt, warum macht Firefox das nicht?

Schließlich, kompiliert Rhino buchstäblich den JavaScript-Java-Byte-Code, so dass Sie alle Geschwindigkeitsvorteile von Java bekommen würden? Wenn nicht, warum laufen Leute nicht mit V8, wenn sie Skripte auf ihren Desktops schreiben?

+1

Rhino kann zu Java-Bytecode kompilieren. https://developer.mozilla.org/en/Rhino_JavaScript_Compiler – Thilo

Antwort

8

V8 ist der schnellste, weil es alle JS zu Maschinencode kompiliert.

SpiderMonkey (was FF verwendet) ist auch schnell, aber kompiliert zu einem Zwischenbyte-Code, nicht Maschinencode. Das ist der große Unterschied zu V8. EDIT- Neuere Firefox-Versionen kommen mit einer neueren Variante von SpideMonkey; TraceMonkey. TraceMonkey erstellt JIT-Kompilierung kritischer Teile und möglicherweise andere intelligente Optimierungen.

Rhino kompiliert Javascript in Java-Klassen, so dass Sie grundsätzlich "Java" -Anwendungen in Javascript schreiben können. Rhino wird auch verwendet, um JS im Backend zu interpretieren und zu manipulieren, und verfügt über vollständigen Code-Verständnis, wie z. B. Reflektion. Dies wird beispielsweise vom YUI Compressor verwendet.

Der Grund, warum Rhino anstelle von V8 überall verwendet wird, ist wahrscheinlich, weil V8 relativ neu ist, so dass viele Projekte bereits Rhino/Spidermonkey als ihre JS-Engine verwenden, zum Beispiel Yahoo-Widgets. (Ich nehme an, dass Sie das mit "Skripten auf ihren Desktops" meinen)

edit- Dieser Link könnte auch einen Einblick geben, warum SpiderMonkey so weit verbreitet ist. Which Javascript engine would you embed in your application?

+2

Umm TraceMonkey macht auch JIT-Übersetzung zu Maschinencode ... Auch ich glaube nicht, dass es überhaupt richtig ist zu sagen, dass V8 "JavaScript" zum Maschinencode "kompiliert" - es ist mehr oder weniger die gleiche Art von JIT-Ansatz wie TraceMonkey. – Pointy

+0

@ Pointy, Der Unterschied AFAIK zwischen TraceMonkey und V8 ist, dass TraceMonkey zu Zwischencode kompiliert, von denen einige JIT kompiliert, um Maschinencode während seiner Ausführung kompiliert. V8 kompiliert alles direkt zum Maschinencode. –

+1

"V8 kompiliert den JavaScript-Quellcode bei der ersten Ausführung direkt in den Maschinencode. Es gibt keine Zwischenbytecodes, keinen Interpreter." Quelle: http://code.google.com/apis/v8/design.html Also grundsätzlich Kompilierung wie ein C-Compiler tun würde. Auch kompiliert V8 alle JS und Tracemonkey JIT tut – adamJLev

3

die Frage zu beantworten, warum nativen Code Vs Byte Code ...

Der native Code schneller ist und für Google eine strategische Entscheidung, weil sie Plan JS einer von ihnen mindestens ChromeOS ist.

Ein gutes Video über diese Frage mit einem Interview mit Lars Bak auf Channel9 erzielte der Mann hinter V8 here

6

Wenn Sie sehen wollen, gefunden werden können, wie die verschiedenen in-Browser stapeln Javascript-Motoren, installieren Sie Safari 4 (ja, es läuft auf Windows jetzt auch!), Chrome V8, Firefox 3.5 und IE 8 (wenn Sie auf Fenster) und führen Sie den Benchmark:

http://www2.webkit.org/perf/sunspider-0.9/sunspider.html

ich glaube, wie Zipfel oben gesagt, die neuer Firefox 3.5 verwendet TraceMonkey, der auch zum Intermediate-Code unter Verwendung von f kompiliert orm von JIT. Es sollte also etwas günstiger mit V8 verglichen werden. Zumindest wird es nicht 10x langsamer als V8 wie Firefox 3 SpiderMonkey (ohne JIT) war.

Für mich ... Safari 4.0.3 war 2.5x schneller als Tracemonky in Firefox 3.5.3 auf Win XP. IE8 war viel viel langsamer. Ich habe im Moment kein Chrome installiert.

Ich weiß nicht, über Rhino Kompilierung zu Java-Bytecode. Wenn es immer noch die dynamischen Eigenschaften von Javascript interpretiert, wie zum Beispiel das Hinzufügen von Attributen zu Objektinstanzen zur Laufzeit (Beispiel obj.someNewAttribute = "someValue", was in Javascript erlaubt ist) ...Ich bin nicht so sicher, dass es vollständig in Bytecode "kompiliert" wird, und Sie können möglicherweise keine bessere Leistung erzielen, als dass Sie nicht jedes Mal, wenn Javascript ausgeführt wird, aus dem JavaScript-Quelltext kompilieren müssen. Denken Sie daran, dass Javascript eine sehr dynamische Syntax wie eval ("x = 10; y = 20; z = x * y") erlaubt; Das bedeutet, dass Sie Codefolgen erstellen können, die zur Laufzeit kompiliert werden. Deshalb würde ich denken, dass Rhino im gemischten Modus interpretiert/kompiliert wird, selbst wenn Sie nach JVM-Bytecode kompiliert haben.

Die JVM ist immer noch ein Interpreter, wenn auch ein sehr guter mit JIT-Unterstützung. Daher denke ich an Rhino-on-JVM als 2 Interpreter-Layer (Interpreter-on-Interpreter) oder Interpreter^2. Während die meisten anderen Javascript-Engines in C geschrieben sind, sollten sie eher wie Interpreter^1 funktionieren. Jede Interpreterschicht kann eine 5- bis 10-fache Leistungsverschlechterung im Vergleich zu C oder C++ (z. B. Perl oder Python oder Ruby) hinzufügen, aber mit JIT kann der Leistungseinbruch viel niedriger in der Größenordnung von 2-4x sein. Und die JVM hat eine der robustesten & ausgereiften JIT-Motoren aller Zeiten.

So wird Ihre Laufleistung definitiv variieren und Sie würden wahrscheinlich davon profitieren, einige ernsthafte Benchmarks zu machen, wenn Sie eine echte Antwort für Ihre beabsichtigte Anwendung auf Ihrer eigenen Hardware haben wollen & OS.

Rhino kann nicht zu schrecklich langsam sein, da ich weiß, dass viele Leute es verwenden. Ich denke, es ist nicht die Geschwindigkeit, sondern die Tatsache, dass es einfach zu codieren/leicht/embeddable/Interpreter ist, die Haken in Java-Bibliotheken, die es perfekt für Scripting/Konfiguration/Erweiterbarkeit Ihres Software-Projekts macht. Einige Texteditoren wie UltraEdit integrieren Javascript sogar als alternative Makro-Skript-Engine. Jeder Programmierer scheint in der Lage zu sein, ziemlich einfach durch Javascript zu stolpern, so dass es auch leicht zu erlernen ist.

Ein Vorteil von Rhino ist, dass es praktisch überall läuft, wo die JVM läuft. Meiner Erfahrung nach kann der Versuch, eigenständig TraceMonkey oder SpiderMonkey zum Erstellen von & über die Befehlszeile auszuführen, auf Systemen wie Windows ein wenig schmerzhaft sein. Und das Einbetten in Ihre eigene Anwendung kann noch zeitaufwendiger sein. Aber die Amortisation einer einbettbaren Sprache würde sich für ein großes Projekt lohnen, verglichen mit der Notwendigkeit, eine eigene Mini-Scripting-Lösung zu erstellen, wenn es das ist, wonach Sie suchen.

Scripting mit Rhino ist wirklich einfach, wenn Sie Java und das Nashorn jar, die Sie gerade Ihr Javascript schreiben und es von der Kommandozeile ausgeführt werden. Ich benutze es die ganze Zeit für einfache Aufgaben.

+0

ich installiert Chrom 4 auf meinem XP-Rechner, und es läuft die SunSpider-Benchmarks zu 3x schneller als Firefox 3.5.3 Ablaufverfolgung Auch entdeckt, dass V8 ist angenehm einfach zu downloaden und zu bauen im Vergleich zu meiner vorherigen Erfahrung mit SpiderMonkey. Natürlich brauchst du svn + python 2.4 + scons 1.0.0 + Visual Studio 2005/2008 (die kostenlose Version von VC++ 2008 soll auch funktionieren), die ich bereits auf meinem Entwickler-PC hatte. Um fair zu sein, vielleicht werde ich zurückgehen und versuchen TraceMonkey erneut zu bauen und sehen, wie es heutzutage stapelt. – linguanerd

+3

Beachten Sie, dass Sunspider nicht die einzige Antwort ist, es ist nur ein JavaScript-Benchmark (wenn auch einer, für den JavaScript-Engine-Autoren stark optimiert haben). –

+0

VC++ 2008 Express (kostenlos) funktioniert für die Kompilierung von V8 mit Scons, tat es früher diese Woche. –

73

Es gibt verschiedene Ansätze zur Ausführung von JavaScript, auch wenn JIT ausgeführt wird. V8 und Nitro (ehemals SquirrelFish Extreme) entscheiden sich für einen JIT mit ganzer Methode, das heißt, sie kompilieren den gesamten JavaScript-Code auf native Anweisungen, wenn sie auf ein Skript stoßen, und führen das dann einfach so aus, als ob es kompilierter C-Code wäre. SpiderMonkey verwendet stattdessen ein "Tracing" -JIT, das zuerst das Skript zu Bytecode kompiliert und interpretiert, aber die Ausführung überwacht und nach "Hotspots" wie Schleifen sucht. Wenn es einen entdeckt, kompiliert es dann nur diesen heißen Pfad zum Maschinencode und führt ihn in der Zukunft aus.

Beide Ansätze haben Vor- und Nachteile. Whole-Methode-JIT stellt sicher, dass alles JavaScript, das ausgeführt wird, kompiliert und als Maschinencode ausgeführt und nicht interpretiert wird, was im Allgemeinen schneller sein sollte. In Abhängigkeit von der Implementierung kann es jedoch bedeuten, dass die Engine Zeit aufwendet, um Code zu kompilieren, der niemals ausgeführt wird oder nur einmal ausgeführt wird und nicht leistungskritisch ist. Außerdem muss dieser kompilierte Code im Speicher abgelegt werden, was zu einer höheren Speicherauslastung führen kann.

Das Tracing-JIT, wie in SpiderMonkey implementiert, kann extrem spezialisierten Code im Vergleich zu einem WIT-JIT erzeugen, da es den Code bereits ausgeführt hat und über die Variablentypen spekulieren kann (zB die Indexvariable in einer for-Schleife behandeln) als native Integer), wo ein JIT mit ganzer Methode die Variable als Objekt behandeln müsste, weil JavaScript nicht typisiert ist und sich der Typ ändern könnte (SpiderMonkey wird einfach "abfallen", wenn die Annahme fehlschlägt, und zur Bytecode-Interpretation zurückkehren) . Das Spacing-JIT von SpiderMonkey funktioniert derzeit jedoch nicht effizient für Code mit vielen Verzweigungen, da die Traces für einzelne Ausführungspfade optimiert sind. Darüber hinaus besteht ein gewisser Mehraufwand bei der Überwachung der Ausführung, bevor entschieden wird, eine Ablaufverfolgung zu kompilieren und dann die Ausführung auf diese Ablaufverfolgung umzustellen. Wenn der Tracer eine Annahme macht, die später verletzt wird (wie zum Beispiel eine Variable, die den Typ ändert), sind die Kosten des Abfallens der Spur und des Zurückschaltens auf das Interpretieren wahrscheinlich höher als bei einem JIT der gesamten Methode.

+8

Beachten Sie, dass Firefox in den dazwischenliegenden Jahren auf die Verwendung eines WIT-JIT sowie "JaegerMonkey" umgestellt und das Tracing-JIT fallen gelassen hat. –