Skip to content

Instantly share code, notes, and snippets.

@bmeurer
Last active October 8, 2017 09:30
Show Gist options
  • Save bmeurer/9a9ddae717e9085a31c4e27d9720b2bc to your computer and use it in GitHub Desktop.
Save bmeurer/9a9ddae717e9085a31c4e27d9720b2bc to your computer and use it in GitHub Desktop.
Isolated test case for the discussion around rest parameters for Node's EventEmitter (https://github.com/nodejs/node/pull/13155#issuecomment-334706721)
// Isolated test case for the discussion around rest parameters for Node's EventEmitter
// https://github.com/nodejs/node/pull/13155#issuecomment-334706721
if (typeof console === 'undefined') console = {log:print};
const N = 2e7;
const TESTS = [];
(function() {
function emitNone(handler, isFn, self) {
if (isFn)
handler.call(self);
else {
var len = handler.length;
var listeners = arrayClone(handler, len);
for (var i = 0; i < len; ++i)
listeners[i].call(self);
}
}
function emitOne(handler, isFn, self, arg1) {
if (isFn)
handler.call(self, arg1);
else {
var len = handler.length;
var listeners = arrayClone(handler, len);
for (var i = 0; i < len; ++i)
listeners[i].call(self, arg1);
}
}
function emitTwo(handler, isFn, self, arg1, arg2) {
if (isFn)
handler.call(self, arg1, arg2);
else {
var len = handler.length;
var listeners = arrayClone(handler, len);
for (var i = 0; i < len; ++i)
listeners[i].call(self, arg1, arg2);
}
}
function emitThree(handler, isFn, self, arg1, arg2, arg3) {
if (isFn)
handler.call(self, arg1, arg2, arg3);
else {
var len = handler.length;
var listeners = arrayClone(handler, len);
for (var i = 0; i < len; ++i)
listeners[i].call(self, arg1, arg2, arg3);
}
}
function emitMany(handler, isFn, self, args) {
if (isFn)
handler.apply(self, args);
else {
var len = handler.length;
var listeners = arrayClone(handler, len);
for (var i = 0; i < len; ++i)
listeners[i].apply(self, args);
}
}
const EventEmitter = class EventEmitter {
constructor() { this._events = Object.create(null); }
emit(type) {
const events = this._events;
const handler = events[type];
if (!handler) return false;
var isFn = typeof handler === 'function';
var len = arguments.length;
switch (len) {
// fast cases
case 1:
emitNone(handler, isFn, this);
break;
case 2:
emitOne(handler, isFn, this, arguments[1]);
break;
case 3:
emitTwo(handler, isFn, this, arguments[1], arguments[2]);
break;
case 4:
emitThree(handler, isFn, this, arguments[1], arguments[2],
arguments[3]);
break;
// slower
default:
args = new Array(len - 1);
for (i = 1; i < len; i++)
args[i - 1] = arguments[i];
emitMany(handler, isFn, this, args);
}
return true;
}
on(type, handler) {
this._events[type] = handler;
}
};
const ee = new EventEmitter();
for (var k = 0; k < 10; k += 1)
ee.on('dummy', function() {});
TESTS.push(
function testDispatchNode() {
ee.emit('dummy');
},
function testDispatchNodeMultiArgs() {
ee.emit('dummy', 5, true);
});
})();
(function() {
const EventEmitter = class EventEmitter {
constructor() { this._events = Object.create(null); }
emit(type, ...args) {
const events = this._events;
const handler = events[type];
if (typeof handler === 'function') {
handler.call(this, ...args);
} else if (handler != null) {
var len = handler.length;
var listeners = arrayClone(handler, len);
for (var i = 0; i < len; ++i)
listeners[i].call(this, ...args);
}
return true;
}
on(type, handler) {
this._events[type] = handler;
}
};
const ee = new EventEmitter();
for (var k = 0; k < 10; k += 1)
ee.on('dummy', function() {});
TESTS.push(
function testDispatchRest() {
ee.emit('dummy');
},
function testDispatchRestMultiArgs() {
ee.emit('dummy', 5, true);
});
})();
function test(fn) {
var result;
for (var i = 0; i < N; i += 1) result = fn();
return result;
}
for (var j = 0; j < TESTS.length; ++j) {
test(TESTS[j]);
}
for (var j = 0; j < TESTS.length; ++j) {
var startTime = Date.now();
test(TESTS[j]);
console.log(TESTS[j].name + ':', (Date.now() - startTime), 'ms.');
}
@bmeurer
Copy link
Author

bmeurer commented Oct 8, 2017

Results with V8 6.1 and 6.2:

$ ./d8-6.1.534.15 bench-event-emitter.js
testDispatchNode: 525 ms.
testDispatchNodeMultiArgs: 643 ms.
testDispatchRest: 644 ms.
testDispatchRestMultiArgs: 822 ms.
$ ./d8-6.2.414.2 bench-event-emitter.js
testDispatchNode: 421 ms.
testDispatchNodeMultiArgs: 504 ms.
testDispatchRest: 389 ms.
testDispatchRestMultiArgs: 475 ms.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment