在这种情况下,扩展原型链如何提高性能?

时间:2018-02-20 20:05:03

标签: javascript performance optimization prototype getter

我有一个长期的假设,即深prototype chains会导致财产访问者的性能下降。当hide the getter or add in the proto Object快速benchmark I threw together导致与我的预期完全相反的结果时,我试图在Object.create()上解释这一点。

这里发生了什么?我是否遗漏了一些明显的东西,或者这是否直接表明我(和其他人)关于prototype链上属性访问者性能的假设是错误的?

设置

const object1 = {
  foo: 'Hello, World!',
  get bar () { return this.foo }
};

const object2 = Object.assign(Object.create({
  get bar () { return this.foo }
}), {
  foo: 'Hello, World!'
});

let result;

测试1

(控制,不含prototype

result = object1.bar;

测试2

(实验,prototype

result = object2.bar;

结果

测试1比测试2慢92.85%,这意味着将get bar () {}放在prototype链而不是对象自己的属性中会导致属性访问器的速度提高14倍。请参阅{{3}}以了解对象的布局是如何不同的。

测试1

79,323,722 ops / s±0.34%

测试2

1,108,762,737 ops / s±0.15%

使用谷歌浏览器63.0.3239.132(官方版本)(64位)在Windows 10 Intel i7-7700K CPU @ 4.20GHz上测试

1 个答案:

答案 0 :(得分:3)

据我所知,这些细节仅适用于V8引擎,我不确定这是如何直接映射到Firefox的实现。

如果没有原型,V8会创建隐藏类来支持对象的属性。对于每个新属性,将创建一个新的隐藏类,然后创建从先前隐藏类到新隐藏类的转换。

然而,这不会发生在原型上,并且从我对该主题的对话中得到一些鲜为人知的事实。换句话说,是的,原型 更快。

  

为了优化原型,V8跟踪常规过渡对象的形状不同。我们不是跟踪过渡树,而是将隐藏的类定制到原型对象,并始终保持快速 - Toon Verwaest (V8 dev)

此设置全部发生在Dynamic Machine Code Generation期间。您看到的两个设置之间的区别在于更复杂的隐藏类路径与更多自定义路径之间的差异。或者,按名称,fastPropertiesWithPrototype对象和slowProperties对象之间的差异,后者使用字典模式。