Object.create(null)

TypeError: Cannot convert object to primitive value

Node.js (v0.12.2) 上で Object.freeze と Object.create を併用すると速度が死ぬ話

Node.js (v0.12.2) でスクリプトが異常に遅かったから色々試したら原因がわかったのでメモ.

次のようなスクリプトで, Object.freeze (あるいは Object.sealObject.preventExtensions) を行ったオブジェクトと行わなかったオブジェクトをObject.create にプロトタイプとして渡したときの速度を比較してみる.

var N = 100000;

console.time("not frozen");
var obj1 = {};
var c1 = N;
while (c1 > 0) {
    c1--;
    Object.create(obj1);
}
console.timeEnd("not frozen");

console.time("frozen");
var obj2 = Object.freeze({});
var c2 = N;
while (c2 > 0) {
    c2--;
    Object.create(obj2);
}
console.timeEnd("frozen");

すると, 私の環境 (Mac OS X 10.9.5 64bit) では Object.freeze していない方は 19 ms 程度, Object.freeze した方は 26 s 程度だった (単位の違いに注意). 他にも実際に Object.freezeObject.create を併用しているスクリプトでも速度を比較したが, Object.freeze を行った方は少なくとも 102 〜 103 倍程度遅いということがわかった.

ちなみに Node.js のフォークである io.js 2.0.1 や, Chrome 42.0.2311.135 (64-bit), Opera beta 29.0.1795.41 なんかの Chromium なブラウザや Firefox 36.04, Safari 7.1.5 などでも確認したが, 速度にそれほど差はなかった (むしろ Object.freeze した方が速いこともあった).

V8 のバージョンを見てみると Node.js 0.12.2 では 3.28.73 *1, io.js 2.0.1 では 4.2.77.20 *2 らしいのだけれど, この間に何か改善があったのかもしれない (ちゃんと探すのがめんどくさかった).

とりあえず, 現状の Node.js はオワコン, io.js を使え ってことでいいだろうか?