JavaScript重箱の隅  新JavaScript入門  JavaScript,Neo-Generation  掲示板  表紙
14. 配列(2)   
JavaScript 重箱の隅
Written 11/16/02
オブジェクト(1)
ここではユーザ定義オブジェクトについてみてみます。
とにかくユーザ定義オブジェクトについては非常に遅いという印象があるのですが、 まず、空のオブジェクトと Array オブジェクトを比べてみます。
    //ループ1
    var a;
    var start_t = new Date();
    for(var j = 1000000; j; j--)
        a = new o_test();
    return (new Date() - start_t) / 1000;
    //ループ2
    var a;
    var start_t = new Date();
    for(var j = 1000000; j; j--)
        a = new Array();
    return (new Date() - start_t) / 1000;
    
    function o_test() { }       //空のオブジェクトの定義
    
    scripts/bench075a.js
    scripts/bench075b.js
    t0 : 712.8443510269016
    ループ1 : 4.41
    ループ2 : 2.41
    ループ1 - ループ2 : 1.99 - 2
 
空だとそんなに遅くはないですね。
ちなみに Array オブジェクトの生成を次のようにするとどうでしょう。
    //ループ3
    var a;
    var start_t = new Date();
    for(var j = 1000000; j; j--)
        a = [ ];
    return (new Date() - start_t) / 1000;
    scripts/bench076a.js
    scripts/bench076b.js
    t0 : 114.68659411822533
    ループ2 : 2.41
    ループ3 : 2.1
    ループ2 - ループ3 : 0.31 - 0.32
 
少し速いだけですね。
話を元に戻して、空じゃなくて引数があってプロパティがある場合はどうでしょう。
    //ループ4
    var a;
    var start_t = new Date();
    for(var j = 1000000; j; j--)
        a = [ ];
    return (new Date() - start_t) / 1000;
    scripts/bench077a.js
    scripts/bench077b.js
    t0 : -1144.294835260531
    ループ1 : 4.43
    ループ4 : 9.11
    ループ1 - ループ4 : -4.69 - -4.67
 
遅くなるのは当たり前ですが、まあ普通でしょうか。
私が遅いと思っているのは 分数オブジェクトなのですが、 これを試してみます。
    //ループ5
    var a;
    var start_t = new Date();
    for(var j = 100000; j; j--)
        a = new Fraction(1, 2);
    return (new Date() - start_t) / 1000;
    scripts/bench078a.js
    scripts/bench078b.js
    t0 : -1777.5391372236865
    ループ4 : 0.93
    ループ5 : 12.66
    ループ4 - ループ5 : -11.75 - -11.72
 
ループの回数が1桁減ってます。 結局 Array オブジェクトの60倍ってことですか。 コンストラクタが長いのでしょうがないですね。
分数オブジェクトはメソッドをコンストラクタで定義しています。
    ...
    this.copy = function() {
        return new Fraction(this.a, this.b);
    }
    this.assign = function(f) {
        this.a = f.a; this.b = f.b;
    }
    ...
 
これは外部に Function オブジェクトを書いて、 メソッドはそのアドレスを代入するだけにすると、 Function オブジェクトの名前が衝突する恐れがあるためです。 こうすると遅いのではないのかという心配はあったのですが。 それを試してみましょう。
    //ループ6
    var a;
    var start_t = new Date();
    for(var j = 1000000; j; j--)
        a = new o_test3(1, 2);
    return (new Date() - start_t) / 1000;
    //ループ7
    var a;
    var start_t = new Date();
    for(var j = 1000000; j; j--)
        a = new o_test4(1, 2);
    return (new Date() - start_t) / 1000;
    
    function o_test3(a, b) {
        this.a = a;
        this.b = b;
        this.add = test_add;
    }
    
    function test_add() {
        return this.a + this.b;
    }
    
    function o_test4(a, b) {
        this.a = a;
        this.b = b;
        this.add = function() {
            return this.a + this.b;
        }
    }
    
    scripts/bench079a.js
    scripts/bench079b.js
    t0 : -1063.4448777640366
    ループ6 : 10.68
    ループ7 : 18.22
    ループ6 - ループ7 : -7.55 - -7.52
 
ループ6はループ4とあまり変わらないのに、ループ7は非常に遅いです。 決定的ですね、これが分数オブジェクトが遅い理由です。
一応、両方でメソッドの実行時間が変わらないかどうか調べてみましょう。
    //ループ8
    var a = new o_test3(1, 2);
    var start_t = new Date();
    for(var j = 1000000; j; j--)
        a.add();
    return (new Date() - start_t) / 1000;
    //ループ9
    var a = new o_test4(1, 2);
    var start_t = new Date();
    for(var j = 1000000; j; j--)
        a.add();
    return (new Date() - start_t) / 1000;
    scripts/bench080a.js
    scripts/bench080b.js
    t0 : -12.591190287071615
    ループ8 : 2.74
    ループ9 : 2.79
    ループ8 - ループ9 : -0.06 - -0.04
 
あんまり変わらないですね。
最後に分数オブジェクトをループ6,8の方式で書いたものと従来のものを 比べてみましょう。
    //ループ10
    var a;
    var start_t = new Date();
    for(var j = 100000; j; j--)
        a = new Fraction2(1, 2);
    return (new Date() - start_t) / 1000;
    //ループ11
    scripts/bench081a.js
    scripts/bench081b.js
    t0 : 350.31550360682405
    ループ5 : 12.87
    ループ10 : 8.88
    ループ5 - ループ10 : 3.96 - 4.01
 
う〜ん、あんまり速くなってない。
first, prev, next, exit