ウェブサイト検索

javascript - オブジェクト参照を配列に保存する際のパフォーマンス問題


なぜv1はv2よりもはるかに遅いのですか?

v1 --

var foo = function (a,b,c) { 
   this.a=a; this.b=b; this.c=c; 
}
var pcs = new Array(32);
for (var n=32; n--;) {
    ref = new foo(1,2,3)
    pcs[n] = ref;    //*****
}

v2 --

var foo = function (a,b,c) { 
   this.a=a; this.b=b; this.c=c; 
}
var pcs = new Array(32);
for (var n=32; n--;) {
    ref = new foo(1,2,3)
    pcs[n] = 1;    //*****
}

「'ref' に新しいオブジェクトへの参照を保持しているので、その参照を配列の要素に代入することは、リテラル値を代入するのとほぼ同じくらい速いだろうと思ったのですが、実際には参照を代入するほうがかなり遅いことが分かりました。これについて誰か説明してもらえますか?V1 でのパフォーマンスを改善するためにできることはありますか?」

フィドル:

http://jsfiddle.net/a0kw9rL1/1/

回答 #1

その参照を配列の要素に単純に割り当てることは、リテラル値を割り当てるのとほぼ同じくらい速いでしょう

はい、基本的にはそうです1。ただし、オブジェクトを割り当てることがここで違いを生む可能性があります。
V2では、refは1回だけ割り当てられ、繰り返し上書きされるだけで、ヒープではなくスタックに割り当てられるかもしれず、デッドコード削除によって完全に最適化されて取り除かれることさえあります。
V1では、refはヒープ上に割り当てる必要があり、新しい場所に繰り返し割り当てられなければなりません。なぜなら、異なるすべてのインスタンスがpcsからアクセス可能だからです。

V1はV21よりも多くのメモリを消費しています。ただし、非常に小さい配列を使用しているため、その差は無視できる程度です。本当に大きな配列を使用すると、違いがわかります: http://jsperf.com/array-reference-assignment/3

[1]: まあ、理由はよくわかりません。でも、それについて説明することはできません。ただ、メモリ使用量をプロファイルするとガベージコレクションが異なるだけです