リテラル, コンストラクタ, それぞれのオブジェクト生成方法のプロファイリングをやってみた

こんにちは. 今日, 研究室の女の子と「new Object()より{}のほうが早いし, new Array()より[]のほうが早いんだよ」みたいなことを喋っていた. たしか何かの本に実際に計測していた結果が載っていて, それを覚えていたのだと思う. 実際, 自分で手を動かして測ったわけではないので怖くなって測ることにした.

計測方法

JavaScriptグラフィックス」に載っている自家製コードプロファイリングを採用する. これは以下のようなプログラムを書いて1秒あたりの実行回数を計測する.

var time_elapsed = 0;
var start_time = new Date().getTime();

for (var iters = 0; time_elapsed < 1000; iters++) {
  // ここでテストコードを実行する
  time_elapsed = new Date().getTime() - start_time;
}
console.log(iters);

毎回, 回数は違うので5回測って, その中央値を採用する.

なぜ,

var start_time = new Date().getTime();
// ここでテストコードを実行する
console.log(new Date().getTime() - start_time);

ではダメなのかというと, 以下のような問題があるから.

  • JSの時間間隔の短いタイマー(setInterval, setTimeout)は不正確
  • イベントからの要求や不定期のGCの発生で結果に影響が出る

実際に測ってみた

実際にテストコードを挟んで実行してみる. テストコードには

var hoge = new Object(); // コンストラクタによる生成
var hoge = {}; // リテラルによる生成

などを実行する. 検証環境はMacOSX 10.7.2(CPU: 2.4GHz IntelCore2Duo, Memory: 4GB).

Firefox 12.0
生成方法 回数
オブジェクト(コンストラクタ) 152206
オブジェクト(リテラル) 172847
配列(コンストラクタ) 145800
配列(リテラル) 174611
Chrome 18.0.1
生成方法 回数
オブジェクト(コンストラクタ) 313398
オブジェクト(リテラル) 350915
配列(コンストラクタ) 306741
配列(リテラル) 332290
番外編 Node 0.4.12
生成方法 回数
オブジェクト(コンストラクタ) 4764825
オブジェクト(リテラル) 5587474
配列(コンストラクタ) 5238278
配列(リテラル) 5597405

結論

  • V8(ChromeとNodeで使われているJSエンジン)はスゴイ...
  • 特にNode...(まあ,ブラウザとは別物ですが)
  • やはり,コンストラクタよりもリテラルで生成するほうが速かった

どうでもいいこと

速度もさることながら

var hoge = new Array();
var foo = new Object();

var hoge = [];
var foo = {};

だったら,タイプ数といい,見栄えといい,後者が良いと思わないっすか?

クロックフォード卿の本に他にもリテラルを使う利点が書かれていた気がする...要確認.

最後に記事のネタを提供してくれた※女史に感謝(最近, ブログのネタ切れ気味・・・).

JavaScriptグラフィックス ―ゲーム・スマートフォン・ウェブで使う最新テクニック

JavaScriptグラフィックス ―ゲーム・スマートフォン・ウェブで使う最新テクニック


JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス

JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス