Repeated calling lists of functions
JavaScript performance comparison
Info
We are doing some heavy iterative work and we need to allow callers to set up custom "pipelines" of functions which will all be executed in order every loop. Each function will be executed hundreds of times. What is the performance hit of providing a nice dynamic API such as EventEmitter for registering the functions, over asking them to just define the functions they want to call and in what order in a custom callback.
Preparation code
<script src="https://raw.github.com/Wolfy87/EventEmitter/master/EventEmitter.min.js">
</script>
<script>
Benchmark.prototype.setup = function() {
REPS = 300;
do1 = do2 = do3 = do4 = function(arg) {
// Sample work
arg * 5;
};
// First implementation, provides only an onEnter method which
// must be called every loop
// "Listeners" are added manually in the required order.
// return values must also be manually handled.
function O1() {}
O1.prototype.onEnter = function(arg) {
arg = do1.call(this, arg);
arg = do2.call(this, arg);
arg = do3.call(this, arg);
arg = do4.call(this, arg);
return arg;
};
o1 = new O1;
// Second implementation
// (Basic EventEmitter implementation; incomplete as it only defines emit())
// This way, functions can be registered in an Array and will be
// invoked using an additional for loop
// To execute the functions, we can emit("enter");
function O2() {
this.events = {};
}
O2.prototype.emit = function(event, arg) {
var listeners = this.events[event];
if (listeners) {
for (var i = 0, l; l = listeners[i]; ++i) {
arg = l.call(this, arg);
}
}
return arg;
};
o2 = new O2;
o2.events["enter"] = [do1, do2, do3, do4];
// https://github.com/Wolfy87/EventEmitter
// Compare with a full-blown EventEmitter implementation
o3 = new EventEmitter;
o3.on("enter", do1);
o3.on("enter", do2);
o3.on("enter", do3);
o3.on("enter", do4);
function compile(funcList) {
var closureVars = [],
fnName,
funcBody = "";
for (var i = 0, l = funcList.length; i < l; ++i) {
closureVars.push((fnName = "f" + i) + ' = funcList[' + i + ']');
funcBody += 'arg = ' + fnName + '.call(this, arg);\n';
}
funcBody += "return arg;";
return Function("funcList",
"var " + closureVars.join(", ") + ";" +
"return function (arg) {" + funcBody + "};"
)(funcList);
}
o4 = {events: {enter: [do1, do2, do3, do4]}};
};
</script>
Test runner
Warning! For accurate results, please disable Firebug before running the tests. (Why?)
Java applet disabled.
| Test | Ops/sec | |
|---|---|---|
Old fashioned callback |
|
pending… |
Basic for-loop event emitter |
|
pending… |
Full event emitter implementation |
|
pending… |
Dynamically unrolled loop |
|
pending… |
You can edit these tests or add even more tests to this page by appending /edit to the URL.
0 comments