push メソッドについて見てみます。
//ループ1
var start_t = new Date();
var a = [ ];
for(var j = 0; j < 200000; j++)
a[j] = j;
return (new Date() - start_t) / 1000;
//ループ2
var start_t = new Date();
var a = [ ];
for(var j = 0; j < 200000; j++)
a.push(j);
return (new Date() - start_t) / 1000;
scripts/bench072a.js
scripts/bench072b.js
t0 : -34.54002493098227
ループ1 : 1.51
ループ2 : 1.91
ループ1 - ループ2 : -0.42 - -0.37
意外にも、
push メソッドを使うほうが遅いんですね。
じゃあ、
length プロパティを使ったときと比べると、
//ループ3
var start_t = new Date();
var a = [ ];
for(var j = 0; j < 200000; j++)
a[a.length] = j;
return (new Date() - start_t) / 1000;
scripts/bench073a.js
scripts/bench073b.js
t0 : -24.501267353163925
ループ3 : 1.59
ループ2 : 1.9
ループ3 - ループ2 : -0.33 - -0.28
やっぱり遅いですね。
push メソッドは、
記述しやすさだけのためにあるんでしょうか。
確かに、この方が速いという理由はあまり思いつかないんだけど。
ついでに
pop メソッドもみておきましょう。
//ループ4
var a = [ ];
var c;
for(var j = 0; j < 10000; j++)
a[a.length] = j;
var start_t = new Date();
for(var j = 1000; j; j--) {
c = a[a.length-1];
a.length--;
}
return (new Date() - start_t) / 1000;
//ループ5
var a = [ ];
var c;
for(var j = 0; j < 10000; j++)
a[a.length] = j;
var start_t = new Date();
for(var j = 1000; j; j--)
c = a.pop();
return (new Date() - start_t) / 1000;
scripts/bench074a.js
scripts/bench074b.js
t0 : -1.0896575746428234
ループ4 : 3.89
ループ5 : 3.91
かかった時間に差があるとはいえない
なんと変わらないんですね。
それにしても
pop メソッドは遅いです。
何をやっているんでしょう。
今度は、
push
する数を変えてかかった時間を測ってみましょう。
10000 20000 50000 100000 200000
ループ1 0.034 0.095 0.243 0.569 1.51
ループ2 0.037 0.103 0.313 0.711 1.91
累乗で近似してみると、ループ1が1.29乗、
ループ2(
pushメソッド)が1.23乗となり、
大きくなると差が開いていく方向です。
pop もみておきましょう。
こちらはあらかじめ
push しておく数を変えて、
1000回
pop するのにかかった時間を測ります。
2000 3000 3500 4000 4500 5000 6000 7000 10000
0.25 0.44 0.63 0.98 1.46 1.84 2.30 2.70 3.89
グラフがないので分かりにくいですが、4000〜5000くらいで挙動不審ですよね。
恐らく4096を境に格納方法が変わってるんじゃないかと思います。
これを仮定して1回の pop にかかる時間を推定してみました。
62.26exp(n/1282) µs (n <= 4096)
0.4126n µs (n > 4096)
n : 配列の大きさ
この両方で n = 4096 のときの
pop する時間を計算すると、
1.518ms
1.690ms
となり、なかなかの接続具合です。