Es gibt eine Menge Kapital C, Kapital S Informatik geht in Javascript über die Tracelemonkey, Squirrelfish und V8-Projekte. Wenden sich irgendwelche dieser Projekte (oder andere) auf die Leistung von DOM-Vorgängen an, oder beziehen sie sich ausschließlich auf die Berechnung von Javascript?Wie beeinflussen die verschiedenen Javascript-Optimierungsprojekte die DOM-Leistung?
Antwort
Die Leistung von reinen DOM-Operationen (getElementById/Tagname/Selector, nextChild, etc) sind nicht betroffen, da sie bereits in reinem C++ sind.
Wie die Verbesserungen der JS-Engine die Leistung beeinflussen, hängt in gewissem Maße von den einzelnen Techniken ab, die für die Leistungsverbesserungen sowie von der Leistung der DOM-> JS-Bridge verwendet werden.
Ein Beispiel für erstere ist die Abhängigkeit von TraceMonkey von allen Aufrufen, die JS-Funktionen betreffen. Da ein Trace den Pfad der Ausführung effektiv in jedem Punkt eingrenzt, an dem der JS Code findet, der nicht inline sein kann (nativer Code, echte polymorphe Rekursion, Ausnahmebehandler), wird der Trace abgebrochen und die Ausführung fällt zurück auf den Interpreter. Die TM-Entwickler machen eine Menge Arbeit, um die Menge an Code zu verbessern, die verfolgt werden kann (einschließlich der Handhabung von polymorpher Rekursion), jedoch ist eine realistische Verfolgung von Aufrufen zu beliebigen nativen Funktionen (z. B. dem DOM) nicht möglich. Aus diesem Grund glaube ich, dass sie versuchen, mehr von DOM in JS (oder zumindest in einer JS-freundlichen Art) zu implementieren. Das heißt, wenn Code rückverfolgbar ist, kann TM eine außergewöhnlich gute Arbeit leisten, da es die meisten "Objekte" auf effizientere und/oder native Äquivalente reduzieren kann (z. B. Maschinen-Ints anstelle der JS-Nummern-Implementierung verwenden).
Javascript (das ist, wo SquirrelFish Extreme lebt) und V8 haben einen ähnlichen Ansatz, dass sie beide JIT alle JS-Code sofort und Code erzeugen, der mehr spekulativ ist (z. B. wenn Sie a*b
tun sie Code erzeugen, a
annimmt, und b
sind Zahlen und fallen auf außergewöhnlich langsamen Code zurück, wenn sie nicht sind). Dies hat eine Reihe von Vorteilen gegenüber der Ablaufverfolgung, nämlich dass Sie den gesamten Code jit können, unabhängig davon, ob er nativen Code aufruft/Ausnahmen auslöst usw., was bedeutet, dass ein einzelner DOM-Aufruf die Leistung nicht zerstört. Der Nachteil ist, dass der gesamte Code ist spekulativ - TM wird Inline-Aufrufe an Math.floor, etc, aber die beste JSC/V8 tun können, wäre ->a=(Math.floor == realFloor) ? inline : Math.floor(0.5)
dies hat Kosten sowohl in Leistung und Speichernutzung, es ist auch nicht besonders machbar. Der Grund dafür ist die Front Compilation, während TM nur JITs code nach der Ausführung hat (und so genau weiß, welche Funktion aufgerufen wurde). JSC und V8 haben keine echte Grundlage um eine solche Annahme zu machen und müssen im Grunde raten (und derzeit keine Versuche Dies). Die einzige Sache, die V8 und JSC versuchen, um dieses Problem zu kompensieren, besteht darin, zu verfolgen, was sie in der Vergangenheit gesehen haben, und dies in den Ausführungspfad zu integrieren, beide verwenden eine Kombination von Techniken, um dieses Zwischenspeichern durchzuführen, in besonders heißen Fällen Sie überschreiben kleine Teile des Befehlsstroms und in anderen Fällen halten sie Außerband-Caches bereit.Grob gesagt, wenn Sie Code haben,
a.x * a.y
V8 und JSC die ‚implizite Typ‘/‚Structure‘ zweimal geht überprüfen - einmal für jeden Zugriff und dann prüfen, ob a.x
und a.y
beide Zahlen sind, während TM erzeugt Code, der den Typ a
nur einmal überprüft, und kann (alle Dinge sind gleich) einfach a.x
und a.y
multiplizieren, ohne zu überprüfen, dass es sich um Zahlen handelt.
Wenn man sich die reine Ausführungsgeschwindigkeit anschaut, gibt es derzeit eine gemischte Sache, da jede Engine bei bestimmten Aufgaben besser zu sein scheint als andere - TraceMonkey gewinnt in vielen reinen Mathe-Tests, V8 gewinnt in stark dynamischen Fällen, JSC gewinnt, wenn es eine Mischung gibt. Natürlich ist das heute nicht der Fall, aber wir arbeiten alle hart daran, die Leistung zu verbessern. Das andere Problem, das ich erwähnte, war die DOM < -> JS Bindungskosten - das kann tatsächlich eine sehr signifikante Rolle in der Webleistung spielen, das beste Beispiel dafür ist Safari 3.1/2 vs Chrome beim Dromaeo Benchmark. Chrome basiert auf dem Safari 3.1/2-Zweig von WebKit, daher ist es ziemlich sicher, dass eine ähnliche DOM-Leistung angenommen wird (Compiler-Unterschiede könnten zu einem gewissen Maß an Varianz führen). In diesem Benchmark schlägt Safari 3.1/2 eigentlich Chrome trotz einer deutlich deutlich langsameren JS-Engine, was im Wesentlichen auf effizientere Bindungen zwischen JSC/WebCore (dom/rendering/etc von WebKit) und V8/WebCore
zurückzuführen istDerzeit im TM DOM Bindungen suchen scheint ungerecht, da sie die ganze Arbeit noch nicht abgeschlossen haben sie (leider) so fallen sie einfach wieder auf den Dolmetscher :-(
..
Errmmm tun wollen, dass ging etwas länger als beabsichtigt, so kurze Antwort auf die ursprüngliche Frage ist "es hängt": D
Gute Antwort, +1 mach dir keine Sorgen über die Länge, detaillierte One-Stop-Antworten sind in SO wünschenswert. – AnthonyWJones
Hehe, vielleicht würde es ebtter bestellt als "Kurze Antwort: kommt drauf an. \ N \ nlange Antwort:
Das ist ein Haufen Gewinn, wenn ich je einen gesehen habe, danke! –
Sie sind pures JavaScript. Wenn nicht ein bestimmter DOM-Methodenaufruf in JS implementiert wird, haben sie wenig Wirkung (um nicht zu sagen, dass keine Arbeit an der Reduzierung der Overhead solcher Anrufe jedoch getan wurde).
DOM-Optimierung ist ein ganzer ‚nother Kessel von
Eichhörnchen
Affen
Spinnen
Fisch ... Das Layout und sogar kommen Rendering-Engines ins Spiel, und jeder Browser hat ihre eigene Implementierung und Optimierungsstrategie.
Technisch das Äquivalent von V8 a nd Tracelemonkey ist JavaScriptCore - Squirrel Fish [Extreme] ist Low-Level-Ausführung-Engine, es macht nicht viel ohne den Rest von JSC. Natürlich ist SquirrelFish nur so viel mehr Spaß * – olliej