JavaScript重箱の隅  新JavaScript入門  JavaScript,Neo-Generation  掲示板  表紙
4. ループ  6. 演算 
JavaScript 重箱の隅
Written 1/26/02
代入
色々な形式の値の代入を試してみました。
    //ループ0 何もしない
    var start_t = new Date();
    for(var j = 20000000; j; j--)
        ;
    return (new Date() - start_t) / 1000;
    
    //ループ1 整数
    var start_t = new Date();
    var x, n;
    n = 0;
    for(var j = 20000000; j; j--)
        x = n;
    return (new Date() - start_t) / 1000;
    
    //ループ2 実数
    var start_t = new Date();
    var x, f;
    f = 0.1;
    for(var j = 20000000; j; j--)
        x = f;
    return (new Date() - start_t) / 1000;
    
    //ループ3 ブーリアン
    var start_t = new Date();
    var x, b;
    b = true;
    for(var j = 20000000; j; j--)
        x = b;
    return (new Date() - start_t) / 1000;
    
    //ループ4 文字列
    var start_t = new Date();
    var x, s;
    s = "a";
    for(var j = 20000000; j; j--)
        x = s;
    return (new Date() - start_t) / 1000;
 
まず、何もしないループ0と整数を代入するループ1を比べます。
    scripts/bench004a.js
    scripts/bench004b.js
    t0 : -196.3116985179109
    ループ0 : 5.31
    ループ1 : 7.67
    ループ0 - ループ1 : -2.39 - -2.34
 
たかが代入なのにすごく時間がかかるんですね。
このループ1とループ2〜4と比較しました。
    scripts/bench005a.js
    scripts/bench005b.js
    t0 : 5.178093290070813
    ループ1 : 7.66
    ループ2 : 7.6
    ループ1 - ループ2 : 0.04 - 0.09
    
    scripts/bench006a.js
    scripts/bench006b.js
    t0 : 0.8359173188596147
    ループ1 : 7.66
    ループ3 : 7.65
    かかった時間に差があるとはいえない
    
    scripts/bench007a.js
    scripts/bench007b.js
    t0 : 0.46072133762151235
    ループ1 : 7.66
    ループ4 : 7.65
    かかった時間に差があるとはいえない
 
なぜか実数の代入は速いんですね。 ただ速いといっても3クロックくらいなので本質的なものかどうかは謎。 単にベンチマークの仕方が悪いのかも。
それより、文字列の代入でも同じなんですね。
じゃあということで、もっと長い文字列の代入は、というと、
    //ループ5
    var start_t = new Date();
    var x, s;
    s = "abcdefghijklmnopqrstuvwxyz";
    for(var j = 20000000; j; j--)
        x = s;
    return (new Date() - start_t) / 1000;
    
    scripts/bench008a.js
    scripts/bench008b.js
    t0 : 0.8326910724956436
    ループ4 : 7.61
    ループ5 : 7.6
    かかった時間に差があるとはいえない
 
文字列の長さには依存しないんですね。
たぶん、変数から変数に代入しているように見えるのは アドレスを代入しているんですね。どちらの変数も同じところを見に行ってる。 確かに、変数というかオブジェクト自体を変えるメソッドって無いし、 それで問題は起きないんですね。
例えば、次のようなスクリプトを考えてみましょう。
    var str = "とつげき";
    dance(str);
    WScript.Echo(str);
    function dance(s) {
        s += "ダンシング";
    }
 
こうすると「とつげき」と表示されるので値渡しだと思っていたのですが、 実はアドレス渡しで、 サブルーチンの中の文は別のアドレスに"とつげきダンシング"という文字列を作って、 sはそこを指すようになるので、strにsの変化は反映されないのではないかと思います。

ついでにオブジェクトもやってみましょう。 これは当然アドレスを代入していると思うのですが。

    //ループ6
    var start_t = new Date();
    var x, ary;
    ary = ["八段鏡餅", "甘酒まんじゅう",
                    "王子るこ定食", "巨大パフェ", "ステーキ丼"];
    for(var j = 20000000; j; j--)
        x = ary;
    return (new Date() - start_t) / 1000;
    
    scripts/bench009a.js
    scripts/bench009b.js
    t0 : -4.214636152114291
    ループ1 : 7.61
    ループ6 : 7.65
    ループ1 - ループ6 : -0.07 - -0.02
 
これもほとんど同じですね。

今度は値を直接代入しましょう。

    //ループ7
    var start_t = new Date();
    var x;
    for(var j = 20000000; j; j--)
        x = 0;
    return (new Date() - start_t) / 1000;
    
    //ループ8
    var start_t = new Date();
    var x;
    for(var j = 20000000; j; j--)
        x = 0.123456789;
    return (new Date() - start_t) / 1000;
    
    //ループ9
    var start_t = new Date();
    var x;
    for(var j = 20000000; j; j--)
        x = "abcdefghijklmnopqrstuvwxyz";
    return (new Date() - start_t) / 1000;
    
    scripts/bench010a.js
    scripts/bench010b.js
    t0 : 0.5464230952685513
    ループ1 : 7.6
    ループ7 : 7.6
    かかった時間に差があるとはいえない
    
    scripts/bench011a.js
    scripts/bench011b.js
    t0 : -6.5858555993793075
    ループ2 : 7.64
    ループ8 : 7.72
    ループ2 - ループ8 : -0.11 - -0.05
    
    scripts/bench012a.js
    scripts/bench012b.js
    t0 : -122.99999999888601
    ループ5 : 7.61
    ループ9 : 9.05
    ループ5 - ループ9 : -1.46 - -1.41
 
文字列の代入はさすがに遅いですね。
じゃあ短い文字列はというと、
    //ループ10
    var start_t = new Date();
    var x;
    for(var j = 20000000; j; j--)
        x = "a";
    return (new Date() - start_t) / 1000;
    
    scripts/bench013a.js
    scripts/bench013b.js
    t0 : 0.8143450710367511
    ループ9  : 9.11
    ループ10 : 9.11
    かかった時間に差があるとはいえない
 
結局よけいにかかっている時間は Stringオブジェクトを作るのにかかっている時間なんですかね。

評価した値を代入するのは、非常に速いです。

    //ループ11
    var start_t = new Date();
    var m, n;
    for(var j = 20000000; j; j--) {
        m = 2;
        n = m;
    }
    return (new Date() - start_t) / 1000;
    
    //ループ12
    var start_t = new Date();
    var m, n;
    for(var j = 20000000; j; j--)
        n = m = 2;
    return (new Date() - start_t) / 1000;
    
    scripts/bench026a.js
    scripts/bench026b.js
    t0 : 151.28972868877562
    ループ9  : 9.96
    ループ10 : 8.04
    ループ9 - ループ10 : 1.89 - 1.94
 
first, prev, next, exit