V8-Version v6.5
Alle sechs Wochen erstellen wir im Rahmen unseres Veröffentlichungsprozesses einen neuen Branch von V8. Jede Version wird direkt vor einem Chrome-Beta-Meilenstein aus dem Git-Master von V8 herausgelöst. Heute freuen wir uns, unseren neuesten Branch, V8-Version 6.5, anzukündigen, der sich bis zur Veröffentlichung im Einklang mit Chrome 65 Stable in mehreren Wochen in der Beta-Phase befindet. V8 v6.5 ist vollgepackt mit allerlei Entwickler-Extras. Dieser Beitrag bietet eine Vorschau auf einige der Highlights als Vorgeschmack auf die Veröffentlichung.
Modus für unzuverlässigen Code
Als Reaktion auf die neueste spekulative Nebenkanalangriffsmethode namens Spectre hat V8 einen Modus für unzuverlässigen Code eingeführt. Wenn Sie V8 einbetten, sollten Sie erwägen, diesen Modus zu nutzen, falls Ihre Anwendung benutzererstellten, nicht vertrauenswürdigen Code verarbeitet. Bitte beachten Sie, dass dieser Modus standardmäßig aktiviert ist, auch in Chrome.
Streaming-Kompilierung für WebAssembly-Code
Die WebAssembly-API stellt eine spezielle Funktion zur Unterstützung der Streaming-Kompilierung in Kombination mit der fetch()
-API bereit:
const module = await WebAssembly.compileStreaming(fetch('foo.wasm'));
Diese API ist seit V8 v6.1 und Chrome 61 verfügbar, obwohl die anfängliche Implementierung tatsächlich keine Streaming-Kompilierung genutzt hat. Mit V8 v6.5 und Chrome 65 nutzen wir jedoch diese API und kompilieren WebAssembly-Module bereits, während die Modulbytes noch heruntergeladen werden. Sobald wir alle Bytes einer einzelnen Funktion heruntergeladen haben, übergeben wir die Funktion an einen Hintergrund-Thread zur Kompilierung.
Unsere Messungen zeigen, dass mit dieser API die WebAssembly-Kompilierung in Chrome 65 auf High-End-Maschinen mit einer Download-Geschwindigkeit von bis zu 50 Mbit/s Schritt halten kann. Das bedeutet, dass wenn Sie WebAssembly-Code mit 50 Mbit/s herunterladen, die Kompilierung dieses Codes abgeschlossen ist, sobald der Download abgeschlossen ist.
Für das folgende Diagramm messen wir die Zeit, die benötigt wird, um ein WebAssembly-Modul mit 67 MB und etwa 190.000 Funktionen herunterzuladen und zu kompilieren. Wir führen die Messungen mit 25 Mbit/s, 50 Mbit/s und 100 Mbit/s Download-Geschwindigkeit durch.
Wenn die Downloadzeit länger ist als die Kompilierungszeit des WebAssembly-Moduls, z. B. im obigen Diagramm mit 25 Mbit/s und 50 Mbit/s, dann schließt WebAssembly.compileStreaming()
die Kompilierung fast unmittelbar ab, nachdem die letzten Bytes heruntergeladen wurden.
Wenn die Downloadzeit kürzer ist als die Kompilierungszeit, dauert WebAssembly.compileStreaming()
etwa so lange, wie es dauern würde, das WebAssembly-Modul ohne vorheriges Herunterladen des Moduls zu kompilieren.
Geschwindigkeit
Wir haben weiter daran gearbeitet, den Schnellweg für JavaScript-Builtins im Allgemeinen zu erweitern und einen Mechanismus hinzugefügt, um eine ruinöse Situation namens „Deoptimierungsschleife“ zu erkennen und zu verhindern. Diese tritt auf, wenn Ihr optimierter Code deoptimiert wird und es keine Möglichkeit gibt, herauszufinden, was schiefgelaufen ist. In solchen Szenarien versucht TurboFan weiterhin zu optimieren und gibt schließlich nach etwa 30 Versuchen auf. Dies würde passieren, wenn Sie etwas tun, um die Form des Arrays in der Callback-Funktion eines unserer Builtins zweiter Ordnung zu ändern. Zum Beispiel das Ändern der length
des Arrays — in V8 v6.5 bemerken wir, wenn dies geschieht, und unterbrechen das Inline-Caching des an diesem Standort aufgerufenen Builtins bei zukünftigen Optimierungsversuchen.
Wir haben den Schnellweg auch erweitert, indem wir viele Builtins inline gesetzt haben, die vorher ausgeschlossen waren, weil es eine Nebenwirkung zwischen dem Laden der aufzurufenden Funktion und dem eigentlichen Aufruf gab, zum Beispiel bei einem Funktionsaufruf. Und String.prototype.indexOf
hat eine 10× Leistungsverbesserung bei Funktionsaufrufen erhalten.
In V8 v6.4 hatten wir die Unterstützung für Array.prototype.forEach
, Array.prototype.map
und Array.prototype.filter
inline umgesetzt. In V8 v6.5 haben wir die Inline-Unterstützung hinzugefügt für:
Array.prototype.reduce
Array.prototype.reduceRight
Array.prototype.find
Array.prototype.findIndex
Array.prototype.some
Array.prototype.every
Darüber hinaus haben wir den Schnellweg für all diese Builtins erweitert. Zunächst hätten wir abgebrochen, wenn wir Arrays mit Gleitkommazahlen gesehen hätten oder (noch häufiger abgebrochen), wenn Arrays „Löcher“ enthalten hätten, z. B. [3, 4.5, , 6]
. Jetzt behandeln wir löchrige Gleitkomma-Arrays überall, außer in find
und findIndex
, wo die Spezifikationsanforderung, Löcher in undefined
zu konvertieren, unsere Bemühungen (vorerst …!) durchkreuzt.
Das folgende Bild zeigt das Verbesserungsdelta im Vergleich zu V8 v6.4 in unseren inlining-Builtins, aufgeschlüsselt in Ganzzahl-Arrays, Gleitkomma-Arrays und Gleitkomma-Arrays mit Lücken. Die Zeit ist in Millisekunden angegeben.
V8 API
Bitte verwenden Sie git log branch-heads/6.4..branch-heads/6.5 include/v8.h
, um eine Liste der API-Änderungen zu erhalten.
Entwickler mit einem aktiven V8-Checkout können git checkout -b 6.5 -t branch-heads/6.5
verwenden, um die neuen Funktionen in V8 v6.5 auszuprobieren. Alternativ können Sie den Beta-Kanal von Chrome abonnieren und die neuen Funktionen bald selbst ausprobieren.