Home

Awesome

<i>Update 09.03.15: "Native Unwrapped" and ClassManager "polymorphic" and "full export" cases need to be removed as irrelevant. Will do that in spare time.</i>

JavaScript class inheritance performance tests

Accurate tests of JavaScript class inheritance models, which model real-world application behaviour with aim to providing better accuracy.

Only the fastest and most popular class systems are tested. For example: speed of Prototype.js classes is about 1% of native, so there is no reason to include it. The same applies to MooTools. Ext.JS is not included, cause it affects results of other tests (from the words of other authors).

##Where to see the results?

##Comparison to other test suites

Creating micro-benchmarks is an art, which requires deep understanding of browser internals and some human adequateness.

For example: test that mixes class generation and method calls is incorrect (inadequate), cause class generation usually happens once, when page is loaded, and it takes much more time than a method call. Some systems, like TypeScript, CoffeeScript and Lava.ClassManager are able to generate classes on server - so it's absolutely incorrect to mix them with browser-only solutions, like John Resig's Class. Authors of such tests can manipulate your opinion by adjusting loop counter numbers. Such bad examples include tests of Fiber.js from LinkedIn and DotNetWise - they do just that.

What else to watch for:

<i>I do not claim absolute correctness of these tests, they are just more relevant than most of others.</i>

##Another bad example: how not to write tests

Let's test speed of counter increment. Preparation code:

// declare a counter in window root:
var counter = 0;
var method = function() { counter++; }

Now the test itself. Nothing more than a loop:

for (var i = 0; i < 10000; i++) {
    method();
}

This test is wrong in many ways:

To create the right tests you should also understand how your benchmark suite works, what is polymorphism in property accessors, scope internals and many other things. If you want to learn more, then I recommend you this site for reference: mrale.ph (it's not mine, but currently it's one of the best sources about JavaScript engine internals).

##Techniques used

These tests try to provide most accurate results, although it's not guaranteed that they are 100% correct. For example: browser vendors can implement different kinds of optimizations, which will lead to wrong results. If I find any mistakes or room for improvement - I will do my best to maintain their quality.

To ensure accuracy, these tests use the following techniques:

if (prevent_inline) {
	// lots of dummy code, which will never be executed
}
if (this.counter > 99) this.counter = this.counter / 2;

When counter hits 100, it's set to 50.

##Explanation of Native

Native model comes in two flavours:

You should notice the difference in method call speed between Native (wrapped) and Native (unwrapped) test cases. When classes are in the window root - Chrome often applies some kind of optimization, which boosts the speed of "Native (unwrapped)" test case twice. It happens time to time, and result is not consistent. To make this optimization happen, your classes must strictly follow the pattern from src/Native/unwrapped.js. At current moment this optimization seems to be disabled by wrapping classes into a closure.

<b>In real world most of your code will be wrapped into a closure:</b> for better compression, isolation, and for module loader compatibility. And inside Node.js environment each module is automatically wrapped in a closure.

So, to summarize this: you should use Native (wrapped) test case as reference - it's the real speed of the Native model. If you put your classes in window root - then you MAY get the speed of Native (unwrapped), but... it does not always happen. Speed boost of unwrapped model may also mean, that there is an error in my test case.

##Changelog

See CHANGELOG.md

##P.S.

To learn more about ClassManager, please visit it's official repository: https://github.com/kogarashisan/ClassManager