読者です 読者をやめる 読者になる 読者になる

JavaScriptのドット演算がDOMとか関係なくホントに遅いのか試してみた

JavaScriptはドット演算が重い」ってのはよく聞いてたのだけど、
DOMとか関係なく重いのかよくわからなくて試してみた。


結果は、やっぱりドットが深くなれば重いと。


以下が試したこと。
パターンは4つ。


obj1:空のオブジェクトで5階層めにアクセスする
obj2:色々なオブジェクトで5階層めにアクセスする
obj3:色々なオブジェクトで1階層めにアクセスする
_obj:obj2の4階層めのオブジェクトから5階層めのオブジェクトにアクセスする


それぞれのオブジェクトを関数に渡して、1000000回ループで測ってみました。
_objの場合は関数に渡す時にobj2の4階層めのオブジェクトを渡しているということです。
あと、「空のオブジェクトだけで深いのと色々なオブジェクトで深いのだと違うのかな?」と思い、
obj2とobj3にはjQueryオブジェクトをぶら下げてます。


それぞれのブラウザの結果は以下。

IE
obj1.ave : 1243.8
obj2.ave : 1628
obj3.ave : 1337.4
_obj.ave : 1372

Opera
obj1.ave : 556.2
obj2.ave : 872
obj3.ave : 684.4
_obj.ave : 662.4

lolifox
obj1.ave : 390.8
obj2.ave : 687.4
obj3.ave : 475
_obj.ave : 434.4

obj1.ave : 257.6
obj2.ave : 389.4
obj3.ave : 284
_obj.ave : 288.8

obj1.ave : 440.4
obj2.ave : 562.6
obj3.ave : 453.2
_obj.ave : 447


obj2みたいに深い階層をたどっちゃうとやっぱり重い。
でも、関数で渡す時に4階層めで渡せばobj3と同じようになると。
とりあえずスッキリした。
1000000回ループもしてこのくらいだから大したことはないと思うけど。
代入とか考えたら変わるのかな。
一応、深い階層にオブジェクトの宣言をする時も同じことが言えるわけだから
あんまり深い階層に宣言しない方が良いのかな。


以下、今回のコード。
おかしなことやってたら教えてください。

<span id="result">bench<br /></span>
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
<script type="text/javascript">
var obj1 = {}; // 空のオブジェクトで深い
var obj2 = {};  // 色々なオブジェクトついてて深い
var obj3 = $;  // 色々なオブジェクトついてて浅い


obj1.a = {};
obj1.a.b = {};
obj1.a.b.c = {};
obj1.a.b.c.d = {};
obj1.a.b.c.d.e = 'obj';

obj2.a = $;
obj2.a.b = $;
obj2.a.b.c = $;
obj2.a.b.c.d = $;
obj2.a.b.c.d.e = 'obj';

obj3.a = 'obj';

function bench(name, obj) {
    var start = new Date();
    var o = {}
    for (var i=0;i<1000000;i++) {
        o =
          (name == 'obj1') ? obj.a.b.c.d.e :
          (name == 'obj2') ? obj.a.b.c.d.e :
          (name == 'obj3') ? obj.a :
        obj.e;
    }
    var end = new Date();
    return end - start;
}

var result = {
  obj1 : [],
  obj2 : [],
  obj3 : [],
  _obj : []
}
for (var i=0;i<5;i++){
    result.obj1.push(bench('obj1', obj1));
    result.obj2.push(bench('obj2', obj2));
    result.obj3.push(bench('obj3', obj3));
    result._obj.push(bench('_obj', obj2.a.b.c.d));
}

var time = {
    sum: {
      obj1:0,
      obj2:0,
      obj3:0,
      _obj:0
    },
    ave: {
      obj1:0,
      obj2:0,
      obj3:0,
      _obj:0
    }
};
for (var key in result) {
    for (var i=0;i<result[key].length;i++)
       time.sum[key] += result[key][i];

    time.ave[key] = time.sum[key] / result[key].length;
}

$('#result')
.append('obj1.ave : ' + time.ave.obj1.toString() + '<br/>')
.append('obj2.ave : ' + time.ave.obj2.toString() + '<br/>')
.append('obj3.ave : ' + time.ave.obj3.toString() + '<br/>')
.append('_obj.ave : ' + time.ave._obj.toString() + '<br/>');
</script>