JavaScript重箱の隅  新JavaScript入門  JavaScript,Neo-Generation  掲示板  表紙
13. 配列(1)  16. オブジェクト(1)   
JavaScript 重箱の隅
Written 7/30/02
配列(2)
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
 
となり、なかなかの接続具合です。
first, prev, next, exit