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

Pat*_*rts 9 javascript getter optimization performance prototype

我有一个长期的假设,即深prototype链会导致物业访问者的性能下降.我试图解释一下隐藏吸气器或添加原型对象时,快速基准测试结果导致了与我期望的相反的结果.

这里发生了什么?我是否遗漏了一些明显的东西,或者这是否彻底证明了我(和其他人)关于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;
Run Code Online (Sandbox Code Playgroud)

测试1

(控制,没有prototype)

result = object1.bar;
Run Code Online (Sandbox Code Playgroud)

测试2

(实验,用prototype)

result = object2.bar;
Run Code Online (Sandbox Code Playgroud)

结果

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

测试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上测试

Tra*_*s J 3

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

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

然而,原型不会发生这种情况,并且从我就该主题进行的对话中来看,这是一个鲜为人知的事实。换句话说,是的,原型更快

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

此设置全部发生在动态机器代码生成期间。您看到的两种设置之间的区别在于更复杂的隐藏类路径与更自定义的路径之间的区别。或者,从名称上看,fastPropertiesWithPrototype 对象和 SlowProperties 对象之间的区别,后者使用字典模式。


归档时间:

查看次数:

204 次

最近记录:

7 年,5 月 前