Skip to content

Commit

Permalink
WIP events: optimize emit()
Browse files Browse the repository at this point in the history
EventEmitter#emit() can be called with many different arguments, but
there are a few that are most common. Increase performance by optimizing
those most common cases. It also drastically decreases the amount of
output from --trace_deopt.
  • Loading branch information
trevnorris committed Jan 21, 2015
1 parent 8b98096 commit 77b0098
Showing 1 changed file with 54 additions and 27 deletions.
81 changes: 54 additions & 27 deletions lib/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,38 +56,14 @@ EventEmitter.prototype.getMaxListeners = function getMaxListeners() {
return $getMaxListeners(this);
};

EventEmitter.prototype.emit = function emit(type) {
var er, handler, len, args, i, listeners;

if (!this._events)
this._events = {};

// If there is no 'error' event listener then throw.
if (type === 'error' && !this._events.error) {
er = arguments[1];
if (this.domain) {
if (!er)
er = new Error('Uncaught, unspecified "error" event.');
er.domainEmitter = this;
er.domain = this.domain;
er.domainThrown = false;
this.domain.emit('error', er);
} else if (er instanceof Error) {
throw er; // Unhandled 'error' event
} else {
throw Error('Uncaught, unspecified "error" event.');
}
return false;
}
function $emitGeneric(type) {
var handler, len, args, i, listeners;

handler = this._events[type];

if (util.isUndefined(handler))
return false;

if (this.domain && this !== process)
this.domain.enter();

if (util.isFunction(handler)) {
switch (arguments.length) {
// fast cases
Expand Down Expand Up @@ -120,10 +96,61 @@ EventEmitter.prototype.emit = function emit(type) {
listeners[i].apply(this, args);
}

return true;
}

function $emitUncaughtError(type, er) {
// If there is no 'error' event listener then throw.
if (this.domain) {
if (!er)
er = new Error('Uncaught, unspecified "error" event.');
er.domainEmitter = this;
er.domain = this.domain;
er.domainThrown = false;
this.domain.emit('error', er);
} else if (er instanceof Error) {
throw er; // Unhandled 'error' event
} else {
throw new Error('Uncaught, unspecified "error" event.');
}
return false;
}

function $emitNoArguments(type) {
var handler = this._events[type];

if (typeof handler === 'function')
handler.call(this);
if (typeof handler !== 'object')
return;

var listeners = handler.slice();
for (var i = 0; i < listeners.length; i++)
listeners[i].call(this);

return true;
}

EventEmitter.prototype.emit = function emit(type) {
var ret;

if (!this._events)
this._events = {};

if (this.domain && this !== process)
this.domain.enter();

if (type === 'error' && !this._events.error)
ret = $emitUncaughtError.apply(this, arguments);
else if (arguments.length === 1)
ret = $emitNoArguments.call(this, type);
else
ret = $emitGeneric.apply(this, arguments);

if (this.domain && this !== process)
this.domain.exit();

return true;
return ret;
};

EventEmitter.prototype.addListener = function addListener(type, listener) {
Expand Down

0 comments on commit 77b0098

Please sign in to comment.