Hatena::Groupjavascript

JavaScriptで遊ぶよ

 | 

2010-11-23

数値キーによるプロパティアクセスの速さ

01:18

なんかおもしろいベンチマークを作った。

オブジェクト配列に数値キーと文字列キーでアクセスするのにどれくらいかかるかという話。

それぞれループ100万回(IE8 以下は10万回)まわしてる。

最初の2つ

  • simple loop
  • "a" + i

は、それぞれ何もしないただのループと、型変換の速さを見るためのループ。

次の

  • ary["a" + i]
  • obj["a" + i]
  • obj["a"x10 + i]
  • obj["a"x50 + i]

は見ての通り。ary は配列で obj はオブジェクト。"a"x10 っていうのは "aaaaaaaaaa" という意味。

  • ary[0 <= i < 1000]
  • ary[2^29 <= i < 2^30]
  • ary[2^30 <= i < 2^31]
  • ary[2^31 <= i < 2^32]
  • ary[2^32 <= i < 2^33]
  • ary[2^33 <= i < 2^34]
  • obj[0 <= i < 1000]
  • obj[2^29 <= i < 2^30]
  • obj[2^30 <= i < 2^31]
  • obj[2^31 <= i < 2^32]
  • obj[2^32 <= i < 2^33]

これらは単純に ary[i] とかなのだけど、i の取る範囲がそれぞれ違うと。

ちなみに配列オブジェクトはどれも空なので、プロトタイプまで巡ってることになる。


結果発表!

Firefox 3.6 Chrome 7 Opera 11b IE 9 pp7 IE 8 (10分の一ループ)
simple loop 11 3 4 1 20
"a" + i 223 55 230 2 115
ary["a" + 1] 369 504 355 446 168
obj["a" + 1] 479 346 335 346 135
obj["a"x10 + 1] 599 570 379 346 147
obj["a"x50 + 1] 631 770 509 531 147
ary[0 <= i < 1000] 24 105 73 23 45
ary[2^29 <= i < 2^30] 25 105 77 432 55
ary[2^30 <= i < 2^31] 24 130 75 438 43
ary[2^31 <= i < 2^32] 705 133 144 453 117
ary[2^32 <= i < 2^33] 734 1405 754 563 110
ary[2^33 <= i < 2^34] 783 1410 757 571 113
obj[0 <= i < 1000] 80 78 64 46 37
obj[2^29 <= i < 2^30] 94 83 55 381 33
obj[2^30 <= i < 2^31] 356 102 52 421 28
obj[2^31 <= i < 2^32] 735 105 145 422 95
obj[2^32 <= i < 2^33] 688 1345 683 641 95
obj[2^33 <= i < 2^34] 733 1347 691 573 98

気付いたこと

  • Firefox配列の文字列アクセスのほうがオブジェクトの文字列アクセスより遅い。
  • 配列の数値アクセスは2^31未満ならどれも速い。
    • IE9 は0から1000までがかなり高速だが、これはちょっとおかしい。(後述)
    • 同様に Firefox の 31bit 未満もちょっとおかしい気がする。simple loop と比べて変わらなさすぎ。JIT が頑張りすぎてこのベンチマークでは意味なかったかも。
  • Opera は配列の数値アクセスは3段ギア。
    • 31bit 未満、31bit、32bit 以上。
  • Chrome と Opera と IE8 は配列の数値アクセスよりオブジェクトの数値アクセスのほうが速い。
  • Firefox と Chrome と Opera はオブジェクトの数値アクセスが3段ギア。
    • でも境界はどれも違う。Firefox は 30bit が中間、Chrome は 30bit と31bit が中間、Opera は上と同じで 31bit が中間。

キーが小さな数字の場合は速いけど、31bit あたりを超える大きな数値キーを使うくらいなら文字列のほうがいいという結論。前回の裏付けになったと思う。(Chrome は前回の結果と違う)

IE9 はちょっとおかしかった。

function test7(range_start) {
    var range_end = range_start + 1000;
    var repeat = ie678  ?  100  :  1000;
    var t = new Date;
    var ary = [];
    var a;
    for (var i = 0; i < repeat; i++) {
        for (var j = range_start; j < range_end; j++) {
            a = ary[j];
        }
    }
    return new Date - t;
}

こんなテスト関数なんだけど、test7(Math.pow(2,10)) って呼んだときとtest7(1024) って呼んだときで20倍も差があったり。

へんなの。

トラックバック - http://javascript.g.hatena.ne.jp/edvakf/20101123
 |