lib: micro-optimize EventEmitter#removeListener()

Replace the call to Array#splice() with a faster open-coded version
that creates less garbage.

Add a new benchmark to prove it.  With the change applied, it scores
a whopping 40% higher.

PR-URL: https://github.com/iojs/io.js/pull/185
Reviewed-By: Chris Dickinson <christopher.s.dickinson@gmail.com>
This commit is contained in:
Ben Noordhuis 2014-12-20 00:04:35 +01:00
parent d0c238cc81
commit d3f8db1244
2 changed files with 31 additions and 1 deletions

View File

@ -0,0 +1,23 @@
var common = require('../common.js');
var events = require('events');
var bench = common.createBenchmark(main, {n: [25e4]});
function main(conf) {
var n = conf.n | 0;
var ee = new events.EventEmitter();
var listeners = [];
for (var k = 0; k < 10; k += 1)
listeners.push(function() {});
bench.start();
for (var i = 0; i < n; i += 1) {
for (var k = listeners.length; --k >= 0; /* empty */)
ee.on('dummy', listeners[k]);
for (var k = listeners.length; --k >= 0; /* empty */)
ee.removeListener('dummy', listeners[k]);
}
bench.end(n);
}

View File

@ -246,7 +246,7 @@ EventEmitter.prototype.removeListener =
list.length = 0;
delete this._events[type];
} else {
list.splice(position, 1);
spliceOne(list, position);
}
if (this._events.removeListener)
@ -318,3 +318,10 @@ EventEmitter.listenerCount = function(emitter, type) {
ret = emitter._events[type].length;
return ret;
};
// About 1.5x faster than the two-arg version of Array#splice().
function spliceOne(list, index) {
for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1)
list[i] = list[k];
list.pop();
}