Alright, I wrote a better test:
function testClassPerf() {
let perfCounter
let elapsed
let before, after
function A() {
this.foo = 'bar';
}
A.prototype.bar = function() {
console.log(this.foo)
}
before = performance.now()
for (perfCounter=0; perfCounter < 100000; perfCounter+=1) {
function A() {
this.foo = 'bar';
}
A.prototype.bar = function() {
console.log(this.foo)
}
}
after = performance.now()
console.log('definition test A: ' + (after-before) + 'ms')
before = performance.now()
for (perfCounter=0; perfCounter < 100000; perfCounter+=1) {
new A()
}
after = performance.now()
console.log('instantion test A: ' + (after-before) + 'ms')
class B {
constructor() {
this.foo = 'bar';
}
bar() {
console.log(this.foo)
}
}
before = performance.now()
for (perfCounter=0; perfCounter < 100000; perfCounter+=1) {
class B {
constructor() {
this.foo = 'bar';
}
bar() {
console.log(this.foo)
}
}
}
after = performance.now()
console.log('definition test B: ' + (after-before) + 'ms')
before = performance.now()
for (perfCounter=0; perfCounter < 100000; perfCounter+=1) {
new B()
}
after = performance.now()
console.log('instantion test B: ' + (after-before) + 'ms')
}
I ran that in a Webpack+Babel project, so the actual source looks like this:
function testClassPerf() {
var perfCounter = undefined;
var elapsed = undefined;
var before = undefined,
after = undefined;
function A() {
this.foo = 'bar';
}
A.prototype.bar = function () {
console.log(this.foo);
};
before = performance.now();
for (perfCounter = 0; perfCounter < 100000; perfCounter += 1) {
var _A = function _A() {
this.foo = 'bar';
};
_A.prototype.bar = function () {
console.log(this.foo);
};
}
after = performance.now();
console.log('definition test A: ' + (after - before) + 'ms');
before = performance.now();
for (perfCounter = 0; perfCounter < 100000; perfCounter += 1) {
new A();
}
after = performance.now();
console.log('instantion test A: ' + (after - before) + 'ms');
var B = (function () {
function B() {
_classCallCheck(this, B);
this.foo = 'bar';
}
_createClass(B, [{
key: 'bar',
value: function bar() {
console.log(this.foo);
}
}]);
return B;
})();
before = performance.now();
var _loop = function () {
var B = (function () {
function B() {
_classCallCheck(this, B);
this.foo = 'bar';
}
_createClass(B, [{
key: 'bar',
value: function bar() {
console.log(this.foo);
}
}]);
return B;
})();
};
for (perfCounter = 0; perfCounter < 100000; perfCounter += 1) {
_loop();
}
after = performance.now();
console.log('definition test B: ' + (after - before) + 'ms');
before = performance.now();
for (perfCounter = 0; perfCounter < 100000; perfCounter += 1) {
new B();
}
after = performance.now();
console.log('instantion test B: ' + (after - before) + 'ms');
}
Here are the results in Chromium 45.0.2454.85 (64-bit) for Linux, on a Macbook Pro 11,5:
definition test A: 224.46000000000004ms
instantion test A: 1.9549999999999272ms
definition test B: 657.0600000000004ms
instantion test B: 3.019999999999527ms
This tells us three things:
- the time it takes to define classes is really slow, but in most cases, the user won’t be defining things conditionally (we’ll be defining classes in modules and exporting them which happens before the app runs (there are no conditional loads of modules in ES6 like in CommonJS, so we won’t be conditionally loading modules later than at the beginning (at least not with current Webpack and Browserify designs, but possibly in the future with ES6 Modules via HTTP/2 (see http://jspm.io for the first implementations of that)))).
- the time it takes to construct instances is much faster.
- the amount of time to instantiate 100,000 of these minimal instances, even with Babel’s version of ES5 classes (compiled from ES6 classes) being 33% slower, is negligible. The amount of time it’ll take to instantiate our engine nodes will be substantially greater than this by a whole lot.
Here’s how long it takes to instantiate 100,000 Famous Engine Nodes using the same technique:
before = performance.now()
for (perfCounter=0; perfCounter < 100000; perfCounter+=1) {
new FamousNode()
}
after = performance.now()
console.log('Famous Engine Node instantiation test: ' + (after-before) + 'ms')
result:
Famous Engine Node instantiation test: 114.11499999999978ms
I’d say it’s safe to use ES6 classes, performance wise.