JavaScript Object property getter benchmarks - part 2

Christian Harms's picture

The object access benchmarks last weeks was not surprising but a factor 5 between access "obj.a" and "obj.getA()" is interesting. In this second part I check the access time for properties on objects, created with ECMAScript 3 getter/setter and with the ECMAScript 5 Object.defineProperty variant (works on IE8+, FF3.7+, newest Webkit and Chrome 5) - see more on ECMAScript 5 compatibility table. Oliver asked to add getter tests - and the results produce differences with factor 15-100.

1. JavaScript property with get

Since ECMAScript 3 (works in FF, Safari 3+, Opera 9.5+, Chrome and IE8) we can define properties with getter and setter instead building manually with functions. John Resig has explained the getter syntax in 2007.

  1.  
  2. var obj = {
  3.   get a() { return 1; },
  4.   get b() { return 1; },  
  5.   get c() { return 1; },
  6.   get d() { return 1; },
  7.   get e() { return 1; },
  8. };
  9.  
  10. JSLitmus.test("ObjectPropertyConstantGet", function()
  11.   { sum = obj.a + obj.b + obj.c + obj.d + obj.e; }
  12. );

The example object is only readable, returns the constant 1 and no setter are defined.

2. JavaScript getter and setter in prototype

Instead of defining it directly in the object the getter and setter can defined in the prototype of the object and the value of a public property will saved in a (per convention private) variable with evil underbar.

  1. function Data() {
  2.     this.a=1, this.b=1, this.c=1, this.d=1, this.e=1;
  3. };
  4. Data.prototype = {
  5.     get a()  { return this._a; },
  6.     get b()  { return this._b; },
  7.     get c()  { return this._c; },
  8.     get d()  { return this._d; },
  9.     get e()  { return this._e; },
  10.     set a(v) { this._a=v; },
  11.     set b(v) { this._b=v; },
  12.     set c(v) { this._c=v; },
  13.     set d(v) { this._d=v; },
  14.     set e(v) { this._e=v; }
  15. };
  16. var obj = new Data();
  17.  
  18. JSLitmus.test("ObjectPropertySetGet", function()
  19.   { sum = obj.a + obj.b + obj.c + obj.d + obj.e; }
  20. );

This getter and setter constructs work like a normal function so the benchmarks should be the same.

3. JavaScript defineProperty

An upgraded property definition looks in ECMAScript 5 like this. First I defined only the three attributes to false - if you more interested read the longer article from John Resig.

  • Writable. If false, the value of the property can not be changed.
  • Configurable. If false, any attempts to delete the property or change its attributes (Writable, Configurable, or Enumerable) will fail.
  • Enumerable. If true, the property will be iterated over when a user does "for (var prop in obj){}" (or similar).

  1. var obj = {};
  2. Object.defineProperty(obj, "a",
  3.        { value: 1, writeable: false, enumerable: false, configurable:false});
  4. Object.defineProperty(obj, "b",
  5.        { value: 1, writeable: false, enumerable: false, configurable:false});
  6. Object.defineProperty(obj, "c",
  7.        { value: 1, writeable: false, enumerable: false, configurable:false});
  8. Object.defineProperty(obj, "d",
  9.        { value: 1, writeable: false, enumerable: false, configurable:false});
  10. Object.defineProperty(obj, "e",
  11.        { value: 1, writeable: false, enumerable: false, configurable:false});
  12.  
  13. JSLitmus.test("ObjectDescriptor", function()
  14.   { sum = obj.a + obj.b + obj.c + obj.d + obj.e; }
  15. );

With all attributes set to false it should be fast than plain objects. My experiments with try out all the variants of false and true has the same results.

4. JavaScript defineProperty with getter/setter

The last example can expanded with getter. It works like example 2.

  1. var obj = {};
  2. var a=1, b=1, c=1, d=1, e=1;
  3. Object.defineProperty(obj, "a", { get: function() { return a; }, set: function(v) { a=v; } });
  4. Object.defineProperty(obj, "b", { get: function() { return b; }, set: function(v) { b=v; } });
  5. Object.defineProperty(obj, "c", { get: function() { return c; }, set: function(v) { c=v; } });
  6. Object.defineProperty(obj, "d", { get: function() { return d; }, set: function(v) { d=v; } });
  7. Object.defineProperty(obj, "e", { get: function() { return e; }, set: function(v) { e=v; } });
  8.  
  9. JSLitmus.test("ObjectDescriptorGet", function()
  10.   { sum = obj.a + obj.b + obj.c + obj.d + obj.e; }
  11. );

Test it in your browser

If you own a compatible browser start your own benchmarks!

The Results

The results for the plain javascript object access started in the first article with the first 8 tests.

All tests with active getter function (ObjectPropertyConstantGet, ObjectPropertySetGet, ObjectDescriptorGet) are terrible slow!


The middle graph is the Firefox Developer Preview 3.7a4, the Opera is version 10.10. All benchmarks are stopped on a eeeBox with Intel Atom N270.

AttachmentSize
objectbench.js.txt4.93 KB