仅仅存在 ES6 setter/getter 就会导致不相关函数的性能下降 (V8)

Iir*_*lin 6 javascript google-chrome v8 node.js

1)创建一个对象并给它一个简单的方法,例如,

let R = {
  f: (x) => Math.sqrt(x)
}
Run Code Online (Sandbox Code Playgroud)

2) 对其性能进行基准测试,例如,调用 f(x) 几百万次 3) 现在添加一个 getter,例如,

let R = {
  f: (x) => Math.sqrt(x),
  get h() {return 0}
}
Run Code Online (Sandbox Code Playgroud)

4) 再次对f(x)进行基准测试。chrome/node(V8 引擎)的性能显着下降。

对于这种奇怪现象有什么解释吗?

这是一个代码笔片段: https: //codepen.io/iiroullin/pen/XWbwoVQ

解决方法:

看起来以旧的 (ES5) 方式定义 getter/setter 并不会破坏 V8 优化。因此,当他们解决 ES6 中的所有问题时,可以使用以下代码来代替 (3):

Object.defineProperty(R, 'h', {get: () => 0})
Run Code Online (Sandbox Code Playgroud)

对于所有 getter/setter 都是如此。

另一个修复:

使用类,请参阅下面的答案

jmr*_*mrk 5

我已为此提交了一个错误:crbug.com/v8/10429

您能否描述一下这种情况在什么情况下(除了微基准测试之外)出现,特别是与在类上定义 getter 相比?以下似乎很快:

class C {
  f(x) { return Math.sqrt(x); }
  get h() { return 0; }
}
let R = new C();

for (...) {
  R.f(...);
}
Run Code Online (Sandbox Code Playgroud)

我认为使用类来定义重要对象目前被认为是“最佳实践”;如果存在类不符合要求的情况,那么最好了解一下,以便引擎可以针对此类模式进行优化。


旁注@JaredSmith:术语“deopt”特指当稍后在编译时做出的假设不成立时必须丢弃优化代码的情况。这不是这里发生的事情。