javascript google-chrome v8

javascript - Descriptor de objeto getter/setter rendimiento en versiones recientes de Chrome/V8



google-chrome (1)

Dado

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; } });

utilizando funciones getter / setter

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

tendrá una disminución en el rendimiento de Chrome / V8 (~ 3x) en comparación con el acceso directo a la propiedad:

obj._a = 2; obj._a;

Esto es comprensible. Y usando descriptor getter / setter

obj.a = 2; obj.a;

causará una disminución de ~ 30 veces en el rendimiento de Chrome (41 a la última), casi tan lento como Proxy . Mientras que Firefox y las versiones anteriores de Chrome usan descriptor getter / setter sin penalización de rendimiento significativa.

¿Cuál es el problema exacto con el rendimiento del descriptor getter / setter en las versiones recientes de Chrome / V8? ¿Es un problema conocido que puede ser monitoreado?

Las mediciones se realizaron con Benchmark.js (motor jsPerf). No puedo proporcionar un enlace a la prueba jsPerf para visualizar la diferencia porque jsPerf se ha equivocado seriamente con sus medidas anti-DDoS, pero estoy seguro de que existen algunas que pueden probar un punto.


Los cambios en el rendimiento son relevantes para codereview.chromium.org/714883003 (los créditos van a @VyacheslavEgorov).

Para evitar problemas de rendimiento, se debe utilizar un prototipo. Esta es una de las pocas razones por las cuales las clases singleton pueden usarse para crear una instancia de un objeto una vez.

Con 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);

O con el azúcar sintáctico ES6:

class Obj { constructor() { this._a = 1; } get a() { return this._a; } set a(val) { this._a = val; } } let obj = new Obj();