2017-04-01 3 views
2

Während JavaScript-Code Refactoring in meinem Projekt habe ich festgestellt, dass einige meiner Schleifen drastisch verlangsamt. Suche nach der Ursache habe ich this SO question gefunden, die Verlangsamung wird durch let Anweisung innerhalb for Schleife und Verschluss Schaffung verursacht. Zu meiner Überraschung let und Verschluss aus der for Schleife bewegt hat nicht geholfen, und mit sogar var statt let für Schleifenvariable hilft nicht, auch weil Verlangsamung durch let verursacht wird nach die for Schleife gelegt. Durch zusätzliche Details zu entfernen Ich habe diesen Code-Schnipsel erhalten:Javascript var vs lassen (de) Optimierung/Verlangsamung Problem in v8 und SpiderMonkey

"use strict" 
 
console.log("========================="); 
 
(function(){ 
 
    var itr = 0; 
 
    function f(){++itr;} 
 
    console.time('without_let'); 
 
    for(var i = 0; i < 50000000; ++i){ 
 
     f(); 
 
    } 
 
    var totals = 0; 
 
    console.timeEnd('without_let'); //chrome: 122ms, FF:102ms 
 
})(); 
 

 
(function(){ 
 
    var itr = 0; 
 
    function f(){++itr;} 
 
    console.time('let_below'); 
 
    for(var i = 0; i < 50000000; ++i){ 
 
     f(); 
 
    } 
 
    let totals = 0; // <--- notice let instead of var 
 
    console.timeEnd('let_below'); //chrome: 411ms, FF:99ms 
 
})(); 
 

 
(function(){ 
 
    let itr = 0; 
 
    function f(){++itr;} 
 
    console.time('let_above_and_in_loop'); 
 
    for(let i = 0; i < 50000000; ++i){ 
 
     f(); 
 
    } 
 
    var totals = 0; 
 
    console.timeEnd('let_above_and_in_loop'); //chrome: 153ms, FF:899ms 
 
})(); 
 

 
(function(){ 
 
    var itr = 0; 
 
    function f(){++itr;} 
 
    console.time('let_in_loop'); 
 
    for(let i = 0; i < 50000000; ++i){ 
 
     f(); 
 
    } 
 
    var totals = 0; 
 
\t \t console.timeEnd('let_in_loop'); //chrome: 137ms, FF:102ms 
 
})();

(auch auf JS Fiddle Hinweis: Verwendung von JS Fiddle zeigt wenig unterschiedliche Ergebnisse, aber ähnliche Verlangsamung ist noch in den gleichen Orten)

Ausführen dieses auf Chrome produziert folgende

without_let: 122ms 
let_below: 411ms <----------- Slowdown for v8 
let_above_and_in_loop: 153ms 
let_in_loop: 137ms 

Irgendein Googeln brachte mich zu the article, das besagt, dass let vor Chrome 56/V8 5.6 eine Deoptimisierung verursachte! aber mein Chrom ist 57.0.2987.133 (64-bit) und v8 ver 5.7.492.71. Weitere Überraschungen versuchen, dies auf Firefox 52.0.2 (32-Bit) zu starten. Hier haben wir Verlangsamung an einem anderen Ort, wenn Variable erstellt mit let innen Verschluss verwendet wird:

without_let: 101.9ms 
let_below: 99ms 
let_above_and_in_loop: 899ms <----- Slowdown for SpiderMonkey 
let_in_loop: 102ms 

Wie ich sehe das Problem ist etwas im Zusammenhang mit so „Temporal Dead Zone“ -Funktion genannt, aber immer noch unklar:

  1. Warum können zwei Hauptbrowser (Haupt-JavaScript-Engines) diese (verschiedenen) Teile des Snippets immer noch nicht optimieren?

  2. Gibt es Workarounds zur Verwendung let (außer mit Babel in var zu drehen lassen)? Angenommen, ich bin in der Lage Optionen Chrome passieren oder auch direkt an v8 über v8::V8::SetFlagsFromCommandLine(&argc, argv, true);

UPD: In Chrome ver 58.0.3029.96, v8 Version 5.8.283.37 correspondng (aconding zu https://omahaproxy.appspot.com/) nach Chrom ermöglicht : // flags/# enable-v8-Zukunft als jmrk unten vorgeschlagen noch Verlangsamung für den dritten Fall (jetzt 2 mal statt 8 mal)

without_let: 157.000ms 
let_below: 155.000ms 
let_above_and_in_loop: 304.000ms 
let_in_loop: 201.000ms 

Firefox 53.0 (32bit)

ist
+1

Es ist nicht so, dass sie * nicht * können, sondern dass sie noch nicht die Zeit gefunden haben, es zu implementieren. Vielleicht möchten Sie einige Fehlerberichte einreichen, um diese zu priorisieren. – Bergi

+1

Hier ist Bericht für v8 https://bugs.chromium.org/p/v8/issues/detail?id=6188 und hier für FF https://support.mozilla.org/en-US/questions/1158956 –

+1

Hier ist auch Bugzilla Artikel https://bugzilla.mozilla.org/show_bug.cgi?id=1362930 –

Antwort

2

Ich kann den V8-Teil der Frage beantworten. Die Verlangsamung, die Sie sehen, ist auf eine Einschränkung des alten optimierenden Compilers (bekannt als "Crankshaft") zurückzuführen. Es wurde in dieser ganzen Zeit nicht angesprochen, da das Team an dem neuen optimierenden Compiler ("Turbofan") gearbeitet hat, der in Chrome 59 ausgeliefert wird (derzeit auf den Canary- und Dev-Kanälen, bald auf Beta!).

In Chrome 58 (derzeit in Beta) können Sie bereits eine Vorschau anzeigen, indem Sie die "Experimentelle JavaScript-Kompilierungspipeline" auf "Aktiviert" setzen (unter chrome://flags/#enable-v8-future). Beachten Sie, dass Chrome 59 einige zusätzliche Leistungsverbesserungen bietet.

Seitennotiz: in einer vorhandenen Codebasis gibt es keinen großen Vorteil bei der Migration zu let, so dass Sie einfach weiter var verwenden können.

+0

Ich habe dies in Chrome ver. 58.0.3029.96 getestet - Optimierung entfernt, dass drastische Verlangsamung, aber immer noch dritten Fall ist fast zweimal langsamer. –