Permalink
Browse files

events: improve .emit() method's speed by ~17%

Avoid accessing arguments array in most common cases (up to 3 arguments).

With attached benchmark, results on master:

  one listener - 524ms, multiple - 3539ms

And with this patch:

  one listener - 445ms, multiple - 3442ms
  • Loading branch information...
1 parent 9f4c098 commit 2d630f69b92f09eb5df1c57ed4ec4021b978c81e @indutny committed Dec 21, 2012
Showing with 59 additions and 9 deletions.
  1. +35 −0 benchmark/eventemitter.js
  2. +24 −9 lib/events.js
View
@@ -0,0 +1,35 @@
+var EventEmitter = require('events').EventEmitter;
+
+// One listener
+!function() {
+ var e = new EventEmitter();
+
+ e.on('data', function(x, y) {
+ });
+
+ console.time('emit - one listener');
+ for (var i = 0; i < 1e7; i++) {
+ e.emit('data', 1, 2);
+ }
+ console.timeEnd('emit - one listener');
+}();
+
+// Multiple listeners
+!function() {
+ var e = new EventEmitter();
+
+ e.on('data', function(x, y) {
+ });
+
+ e.on('data', function(x, y) {
+ });
+
+ e.on('data', function(x, y) {
+ });
+
+ console.time('emit - multiple listeners');
+ for (var i = 0; i < 1e7; i++) {
+ e.emit('data', 1, 2);
+ }
+ console.timeEnd('emit - multiple listeners');
+}();
View
@@ -50,23 +50,23 @@ EventEmitter.prototype.setMaxListeners = function(n) {
// non-global reference, for speed.
var PROCESS;
-EventEmitter.prototype.emit = function(type) {
+EventEmitter.prototype.emit = function(type, a1, a2) {
// If there is no 'error' event listener then throw.
if (type === 'error') {
if (!this._events || !this._events.error ||
(isArray(this._events.error) && !this._events.error.length))
{
if (this.domain) {
- var er = arguments[1];
+ var er = a1;
er.domain_emitter = this;
er.domain = this.domain;
er.domain_thrown = false;
this.domain.emit('error', er);
return false;
}
- if (arguments[1] instanceof Error) {
- throw arguments[1]; // Unhandled 'error' event
+ if (a1 instanceof Error) {
+ throw a1; // Unhandled 'error' event
} else {
throw new Error("Uncaught, unspecified 'error' event.");
}
@@ -91,10 +91,10 @@ EventEmitter.prototype.emit = function(type) {
handler.call(this);
break;
case 2:
- handler.call(this, arguments[1]);
+ handler.call(this, a1);
break;
case 3:
- handler.call(this, arguments[1], arguments[2]);
+ handler.call(this, a1, a2);
break;
// slower
default:
@@ -115,9 +115,24 @@ EventEmitter.prototype.emit = function(type) {
this.domain.enter();
}
}
- var l = arguments.length;
- var args = new Array(l - 1);
- for (var i = 1; i < l; i++) args[i - 1] = arguments[i];
+ var l = arguments.length,
+ args;
+
+ switch (l) {
+ case 0:
+ args = [];
+ break;
+ case 1:
+ args = [ a1 ];
+ break;
+ case 2:
+ args = [ a1, a2 ];
+ break;
+ default:
+ args = new Array(l - 1);
+ for (var i = 1; i < l; i++) args[i - 1] = arguments[i];
+ break;
+ }
var listeners = handler.slice();
for (var i = 0, l = listeners.length; i < l; i++) {

0 comments on commit 2d630f6

Please sign in to comment.