Object.create(null) は速いの?
- カテゴリ:
- JavaScript
- コメント数:
- Comments: 0
◆ {} のほうが速い
◆ プロトタイプ的に速そうと思って変えると逆効果
◆ toString とかがいらない場合以外は使う必要なし
◆ プロトタイプ的に速そうと思って変えると逆効果
◆ toString とかがいらない場合以外は使う必要なし
Github であれこれ眺めてると最適化として
を
に変更してるものがありました
これ速いのでしょうか?
プロトタイプ的には見るものが減りますが 特殊なオブジェクトって感じがするのでリテラルから作るもののほうが最適化されてそうに思います
あと見た目的にも {} のほうがいい気がします
本当に効果があるのか調べてみました
実行したのは Chrome 77 です
最近はほとんどが Chrome 系 (V8) なので速度チューニングをするなら Chrome に合わせておけば良いでしょう
作った後に存在するプロパティとしないプロパティのそれぞれにアクセスします
結果はリテラルの {} のほうが速かったです
2 倍まではいきませんが誤差ではなく明確に違うレベルです
速くなりそうな部分はプロトタイプのチェーンを見ない部分なので 存在しないプロパティアクセスです
今回はそこに焦点を当てた比較にします
それぞれの方法で作った空のオブジェクトを事前に用意しておきます
それに対して プロパティアクセスの時間のみを比較します
10 倍以上の差で リテラルのほうが速いです
というわけで Object.create(null) は特別 Object.prototype を継承しないオブジェクトが欲しい場合以外に使う必要はないですね
Object.assign({}, value)
を
Object.assign(Object.create(null), value)
に変更してるものがありました
これ速いのでしょうか?
プロトタイプ的には見るものが減りますが 特殊なオブジェクトって感じがするのでリテラルから作るもののほうが最適化されてそうに思います
あと見た目的にも {} のほうがいい気がします
本当に効果があるのか調べてみました
実行したのは Chrome 77 です
最近はほとんどが Chrome 系 (V8) なので速度チューニングをするなら Chrome に合わせておけば良いでしょう
比較1
{} のときと Object.create(null) のときで比較します作った後に存在するプロパティとしないプロパティのそれぞれにアクセスします
const obj = {x: 1, y: 2, z: 3}
function caseA(){
const value = Object.assign({}, obj)
return value.x + value.a
}
function caseB(){
const value = Object.assign(Object.create(null), obj)
return value.x + value.a
}
function measureA(){
console.time("A")
for(let i=0;i<1000000;i++){
caseA()
}
console.timeEnd("A")
}
function measureB(){
console.time("B")
for(let i=0;i<1000000;i++){
caseB()
}
console.timeEnd("B")
}
measureA()
measureB()
measureA()
measureB()
measureA()
measureB()
A: 59.525146484375ms
B: 90.313720703125ms
A: 55.327880859375ms
B: 95.740966796875ms
A: 59.291015625ms
B: 89.926025390625ms
結果はリテラルの {} のほうが速かったです
2 倍まではいきませんが誤差ではなく明確に違うレベルです
比較2
作るのは関数を呼び出す以上遅いのかもしれません速くなりそうな部分はプロトタイプのチェーンを見ない部分なので 存在しないプロパティアクセスです
今回はそこに焦点を当てた比較にします
それぞれの方法で作った空のオブジェクトを事前に用意しておきます
それに対して プロパティアクセスの時間のみを比較します
const objA = {}
const objB = Object.create(null)
function measureA(){
console.time("A")
for(let i=0;i<1000000;i++){
objA.a
objA.b
objA.c
}
console.timeEnd("A")
}
function measureB(){
console.time("B")
for(let i=0;i<1000000;i++){
objB.a
objB.b
objB.c
}
console.timeEnd("B")
}
measureA()
measureB()
measureA()
measureB()
measureA()
measureB()
A: 3.55419921875ms
B: 46.693115234375ms
A: 3.158935546875ms
B: 49.787109375ms
A: 0.614990234375ms
B: 49.0361328125ms
10 倍以上の差で リテラルのほうが速いです
というわけで Object.create(null) は特別 Object.prototype を継承しないオブジェクトが欲しい場合以外に使う必要はないですね