I've had a long-standing assumption that deep prototype
chains resulted in performance deterioration for property accessors. I was trying to explain that on hide the getter or add in the proto Object when a quick benchmark I threw together resulted in quite the opposite outcome from what I was expecting.
What is going on here? Am I missing something obvious, or does this outright demonstrate that my (and others') assumption about the performance of property accessors on the prototype
chain was wrong?
Setup
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;
Test 1
(control, without prototype
)
result = object1.bar;
Test 2
(experiment, with prototype
)
result = object2.bar;
Outcome
Test 1 ran 92.85% slower than Test 2, which means that placing get bar () {}
in the prototype
chain rather than in the object's own properties results in a 14x speed increase for the property accessor. See Object.create()
to understand how the layout of the object is different.
Test 1
79,323,722 ops/s ±0.34%
Test 2
1,108,762,737 ops/s ±0.15%
Tested on Windows 10 Intel i7-7700K CPU @ 4.20GHz using Google Chrome 63.0.3239.132 (Official Build) (64-bit)