Skip to content

Commit d3f8db1

Browse files
committed
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: #185 Reviewed-By: Chris Dickinson <christopher.s.dickinson@gmail.com>
1 parent d0c238c commit d3f8db1

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

benchmark/events/ee-add-remove.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
var common = require('../common.js');
2+
var events = require('events');
3+
4+
var bench = common.createBenchmark(main, {n: [25e4]});
5+
6+
function main(conf) {
7+
var n = conf.n | 0;
8+
9+
var ee = new events.EventEmitter();
10+
var listeners = [];
11+
12+
for (var k = 0; k < 10; k += 1)
13+
listeners.push(function() {});
14+
15+
bench.start();
16+
for (var i = 0; i < n; i += 1) {
17+
for (var k = listeners.length; --k >= 0; /* empty */)
18+
ee.on('dummy', listeners[k]);
19+
for (var k = listeners.length; --k >= 0; /* empty */)
20+
ee.removeListener('dummy', listeners[k]);
21+
}
22+
bench.end(n);
23+
}

lib/events.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ EventEmitter.prototype.removeListener =
246246
list.length = 0;
247247
delete this._events[type];
248248
} else {
249-
list.splice(position, 1);
249+
spliceOne(list, position);
250250
}
251251

252252
if (this._events.removeListener)
@@ -318,3 +318,10 @@ EventEmitter.listenerCount = function(emitter, type) {
318318
ret = emitter._events[type].length;
319319
return ret;
320320
};
321+
322+
// About 1.5x faster than the two-arg version of Array#splice().
323+
function spliceOne(list, index) {
324+
for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1)
325+
list[i] = list[k];
326+
list.pop();
327+
}

0 commit comments

Comments
 (0)