2016-09-22 13 views
1

私はループ最適化(N.Zakas、Javascript Optimization)について読んでいます。そこで、arraysinverse loopを使用すると、ダイレクトループよりも最適化されていると書かれています。私は予想外の結果を持って、チェック条件+(1式で)
を変数iを増加させるが - チェック条件
- - 変数増加iループ最適化の変更方向

for(i = length;i--;) 

for(var i = 0; i < length; i++){...} 

:完全に論理的なようですChromeの場合

var len = 100000000, 
arr = new Array(len), 
i = len - 1, 
start = new Date(), 
end; 

for(i = 0; i < len; i++){ 
    arr[i] = 1; 
} 

end = new Date(); 

console.log(end - start); 

直接ループのリターン結果に近い4500msが、逆ループ... 9500ms!

なぜですか?

+1

"より最適化され、直接ループです。" ---それはほとんど意味がありません。 – zerkms

+1

N. Zakasは、アンローリングループとDuffs Deviceという技術(https://en.wikipedia.org/wiki/Duff%27s_device)について話していました。 'for'ループではなく' while'ループを使います。 – colecmc

+0

ok、パフォーマンスの範囲を良くしてみよう –

答えて

1

for(i = length;i--;)にコードが少なくなったからといって、処理が少なくなっているわけではありません。 iは依然としてインクリメントされなければならず(この場合はデクリメントされる)、まだチェックが行われる必要があります(前にはi < lengthだったので、今度はi != 0です)。

for(i = 0; i < length; i++)は非常に一般的な構造であるため、最適化するのが非常に一般的です(現代のコンパイラ/インタプリタに明示的に最適化するために投資されたリソースがあるためです)。しかし、私はこれが推測だと認めます。

for(i = 0; i < arr.length; i++) arr.splice(i,1);は、配列の最初の要素を削除し、すべてのシフトであるかもしれない:あなたは配列の内容を飛び出しているときに反復処理が後方は、おそらく速度の大幅な増加を示すだろう

一つのケースがあります他の要素は、ボンネットの下にそのスポットを埋めるために後方に移動する。

に対し:

for(i = arr.length; i--;) arr.splice(i,1);は、ボンネットの下に、配列の長さを増減のみ必要な場合があります(はるかに安いです!)。

これが最適化であるかどうかはわかりませんが、タケウェイではありません。「逆方向反復は高速です!」一般的な意味で。

0

はい、iterating an array backwards can be fasterです。しかし、あなたがここでやっていることではありません。あなたはの配列を逆にしていますが、これはかなり奇妙です(読んでください:あまり最適化されていません)。

最初に最も高いインデックスを割り当てることを開始すると、配列はスパース配列として開始されます。これは、連続配列よりもはるかに効率が悪いことです。エンジンが実行していることが実現したら、割り当て自体が遅くなるか、通常の配列に変換されます。
逆に、0から始めると、エンジンは必要に応じて配列を拡張し、最初から効率的なメモリ表現を使用します。 Btw、私はarr.fill(1)がもっと速くなることを期待しています。