もっと速くするために(トップレベルオブジェクトの省略)

昨日の続きです。

ブラウザで動作する JavaScript では、トップレベルオブジェクト(window)を省略できます。これにより、window.setTimeout や window.document と書くかわりに setTimeout や document と書いても動作します。

今日は、省略すると速くなるのか調べました。

window.userObject1 = 0; // プリミティブ型
window.userObject2 = []; // Array
window.userObject3 = {}; // Hash

// window.xxx でアクセス
function job1(n) {
  for(var i = 0; i < n; ++i) {
    ++window.userObject1;
    window.userObject2.push(i);
    window.userObject3[i] = i;
  }
}
// alias(win = window) でアクセス
function job2(n) {
  for(var i = 0, win = window; i < n; ++i) {
    ++win.userObject1;
    win.userObject2.push(i);
    win.userObject3[i] = i;
  }
}
// window を省略
function job3(n) {
  for(var i = 0; i < n; ++i) {
    ++userObject1;
    userObject2.push(i);
    userObject3[i] = i;
  }
}

jobn を 10万回コール, n = 1

単位はms, IE6 と IE7 はそれぞれ別の PC で測定し、IE8 とその他のブラウザは同じ PC で測定しています。

job1 job2 job3
IE 6.0 7719 7281 5125
IE 7.0 2917 2808 2044
IE 8.0 2453 2438 1375
Opera 9.64 750 469 265
Opera 10 437 344 250
Firefox 2.0 1031 1000 750
Firefox 3.0 988 789 174
Firefox 3.5 1027 809 208
Firefox 3.5(JIT) 1024 822 201
Safari 4.0 118 126 49
Google Chrome 155 93 16

jobn を 1000回コール, n = 100

job1 job2 job3
IE 6.0 5922 5734 3979
IE 7.0 2091 1965 1280
IE 8.0 2391 2344 1312
Opera 9.64 672 281 219
Opera 10 391 250 203
Firefox 2.0 719 656 422
Firefox 3.0 1016 642 136
Firefox 3.5 967 639 169
Firefox 3.5(JIT) 966 635 163
Safari 4.0 126 134 57
Google Chrome 191 46 14

jobn を 1回コール, n = 10万

job1 job2 job3
IE 6.0 6063 5968 3938
IE 7.0 2215 2153 1389
IE 8.0 2453 2422 1344
Opera 9.64 688 281 234
Opera 10 391 266 218
Firefox 2.0 890 750 547
Firefox 3.0 1118 722 221
Firefox 3.5 1080 712 226
Firefox 3.5(JIT) 1086 732 232
Safari 4.0 252 212 141
Google Chrome 168 51 36

まとめ

  • window を省略すると速くなります
    • window オブジェクト直下の要素は、名前解決において特別な扱いを受けているようです
      • 各ブラウザで足並みが揃っているので、最適化しやすく最適化の効果が高いポイントなのでしょうね
  • Firefox3.5(JIT ON) よりも Firefox2 のほうが体感的に速かった(CPU 負荷的にも)
    • JIT ON/OFF で結果に差が見られませんでした。最適化の対象外なのかもしれませんね
  • document のアクセスを高速化するには ⇒ amachang の 「一行で IE の JavaScript を高速化する方法」を掘り下げてみた - latest log

おまけ

window. userObject1 だけでテストした結果。
Firefox2 のスコアに注目です。

// window.xxx でアクセス
function job1(n) {
  for(var i = 0; i < n; ++i) {
    ++window.userObject1;
  }
}
// alias でアクセス
function job2(n) {
  for(var i = 0, win = window; i < n; ++i) {
    ++win.userObject1;
  }
}
// window を省略
function job3(n) {
  for(var i = 0; i < n; ++i) {
    ++userObject1;
  }
}

jobn を 10万回コール, n = 1

job1 job2 job3
IE 6.0 3359 3313 2297
IE 7.0 1092 1045 718
IE 8.0 1078 1094 563
Opera 9.64 250 266 93
Opera 10 156 156 94
Firefox 2.0 485 484 328
Firefox 3.0 470 475 95
Firefox 3.5(JIT) 460 468 108
Safari 4.0 31 30 3
Google Chrome 75 81 2

jobn を 1000回コール, n = 100

job1 job2 job3
IE 6.0 2312 2234 1391
IE 7.0 702 1014 468
IE 8.0 1000 937 454
Opera 9.64 187 63 47
Opera 10 93 63 31
Firefox 2.0 188 172 62
Firefox 3.0 424 301 58
Firefox 3.5(JIT) 404 292 68
Safari 4.0 28 27 1
Google Chrome 70 31 1

jobn を 1回コール, n = 10万

job1 job2 job3
IE 6.0 2359 2266 1406
IE 7.0 717 687 406
IE 8.0 969 968 469
Opera 9.64 203 62 32
Opera 10 109 47 47
Firefox 2.0 188 172 62
Firefox 3.0 415 288 57
Firefox 3.5(JIT) 407 299 73
Safari 4.0 27 27 1
Google Chrome 74 33 1