2017-04-01 23 views
2

私のプロジェクトでJavaScriptコードのリファクタリングをしているうちに、ループの一部が大幅に遅くなることがわかりました。私が見つけた根本的な原因を検索すると、が遅くなり、letの文内にループとクロージャの作成が発生します。 forループの外にletと閉鎖を動かす私の驚きに は助けにはならなかった、とさえ減速がletによって引き起こされるので、ループ変数のためのvar代わりのletを使用しても解決しないforループの後を置きました。Javascript var vs v8と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 
 
})();

(もJS Fiddle注:JSフィドルを使用すると、少し異なる結果を示したが、同様の減速はまだ同じ場所に存在している私は、このコードスニペットを得てきた余分な詳細を除去することにより )Chromeでこれを実行する

以下を生成し

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

何人かのグーグルがthe articleに私をもたらして、letがChrome 56/V8 5.6より前の最適化解除を引き起こしたと述べました!私のクロムは57.0.2987.133(64ビット)とv8 ver 5.7.492.71です。 これをFirefox 52.0.2(32ビット)で実行しようとすると、さらに驚きました。

:私は、問題は多少ので、「一時的なデッド・ゾーン」と呼ばれる機能が、まだ不明に関連する見たよう

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

:ここでは、letで作成した変数は、クロージャ内で使用されている別の場所、の減速を持っています

  1. 2つの主要なブラウザ(主要なJavaScriptエンジン)がまだスニペットのそれらの(異なる)部分を最適化できないのはなぜですか?

  2. 以外はを使用していますが、バベルを使ってvarに変換することはできません)クロムを有効にした後(https://omahaproxy.appspot.com/にaconding)V8バージョン5.8.283.37をcorrespondng 58.0.3029.96版Chromeの場合 、:私はv8::V8::SetFlagsFromCommandLine(&argc, argv, true);

UPD経由してV8にも、直接Chromeにオプションを渡すか、することができるよと仮定://フラグ/#有効-V8-未来をjmrkは、以下第三のケースのための減速がまだある(今の2倍の代わりに8回)

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

のFirefox 53.0(32ビット)

を示唆されるように
+1

彼らは*できないのではなく、まだ実装する時間が見つけられていないということではありません。バグレポートを提出して、優先順位を付けることができます。 – Bergi

+1

v8のレポートはこちらhttps://bugs.chromium.org/p/v8/issues/detail?id=6188 、FFはこちらhttps://support.mozilla.org/en-US/questions/1158956 –

+1

こちらもBugzillaのアイテムです。https://bugzilla.mozilla.org/show_bug.cgi?id=1362930 –

答えて

2

質問のV8部分に答えることができます。あなたが見ている減速は、古い最適化コンパイラ(「クランクシャフト」として知られている)の制限に起因します。このチームは、Chrome 59で出荷されている新しい最適化コンパイラ(「Turbofan」)(現在ベータ版でCanaryとDevチャンネルに出荷中)に取り組んでいるため、このすべての段階で対処されていません。

Chrome 58(現在ベータ版)では、「実験的なJavaScriptコンパイルパイプライン」を「有効」(chrome://flags/#enable-v8-future)に設定してプレビューすることができます。 Chrome 59では、さらに2つのパフォーマンスが向上することに注意してください。

サイドノート:既存のコードベースでは、letへの移行にはあまり効果がありませんので、そのままvarを使用してください。

+0

Chromeのバージョン58.0.3029.96でこれをテストしました。最適化が大幅に減速されましたが、まだ3番目のケースはほぼ2倍遅くなっています。 –