【问题标题】:Object descriptor getter/setter performance in recent Chrome/V8 versions最近 Chrome/V8 版本中的对象描述符 getter/setter 性能
【发布时间】:2016-07-20 04:41:22
【问题描述】:

给定

var obj = {};

var _a = 1;

obj._a = 1;

obj.aGetter = function() {
  return _a;
}

obj.aSetter = function(val) {
  _a = val;
}

Object.defineProperty(obj, 'a', {
  enumerable: true,
  get: function () {
    return _a;  
  },
  set: function(val) {
    _a = val;
  }     
});

使用 getter/setter 函数

obj.aSetter(2);
obj.aGetter();

与直接访问属性相比,Chrome/V8 性能会有所下降(~3 倍):

obj._a = 2;
obj._a;

这是可以理解的。并使用描述符 getter/setter

obj.a = 2;
obj.a;

将导致 Chrome 性能下降 ~30 倍(从 41 到最新) - 几乎与 Proxy 一样慢。而 Firefox 和较旧的 Chrome 版本使用描述符 getter/setter 并没有显着的性能损失。

在最近的 Chrome/V8 版本中,描述符 getter/setter 性能的确切问题是什么?这是一个可以监控的已知问题吗?

测量是使用 Benchmark.js(jsPerf 引擎)完成的。我无法提供 jsPerf 测试的链接来可视化差异,因为 jsPerf 的反 DDoS 措施已经被严重搞砸了,但我确信现有的措施可以证明这一点。 p>

【问题讨论】:

  • 在直接访问中旧版 Chrome 与新版相比如何——它们变得更快,还是访问器性能真的下降了?
  • Afaik,getter/setter 在 V8 中没有得到很好的优化。
  • @Bergi 描述符访问器似乎在 GC
  • @estus 导致回归的提交是codereview.chromium.org/714883003,它删除了用于从转换冲突中恢复的代码。一般来说,在 V8 中,最好将 getter/setter 放在原型上 - 而不是放在直接对象上以避免这种情况。
  • @VyacheslavEgorov 很好的提示,当在原型上定义描述符时确实存在优化。感谢您的研究工作,如果您愿意,可以将其作为答案提交。

标签: javascript google-chrome v8


【解决方案1】:

性能变化与this Chromium issue 相关(致谢@VyacheslavEgorov)。

为避免性能问题,应改用原型。这是单例类可用于实例化对象一次的少数原因之一。

使用 ES5:

var _a = 1;

function Obj() {}

Object.defineProperty(Obj.prototype, 'a', {
  enumerable: true,
  get: function () {
    return _a;  
  },
  set: function(val) {
    _a = val;
  }     
});

var obj = new Obj();
// or
var obj = Object.create(Obj.prototype);

或者使用 ES6 语法糖:

class Obj {
  constructor() {
    this._a = 1;
  }

  get a() {
    return this._a;
  }

  set a(val) {
    this._a = val;
  }     
}

let obj = new Obj();

【讨论】:

  • 哇,这一个简单的步骤 - 将 getter 放入原型 - 让一切变得不同,这有点令人难以置信。
猜你喜欢
  • 2014-11-03
  • 2014-09-12
  • 2013-09-26
  • 1970-01-01
  • 2017-12-23
  • 1970-01-01
  • 1970-01-01
  • 2015-01-21
  • 2011-11-14
相关资源
最近更新 更多