From 77b00987c2ec770ae17a27804e23473577da63a4 Mon Sep 17 00:00:00 2001 From: Trevor Norris Date: Tue, 20 Jan 2015 15:59:54 -0800 Subject: [PATCH] WIP events: optimize emit() 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. --- lib/events.js | 81 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 54 insertions(+), 27 deletions(-) diff --git a/lib/events.js b/lib/events.js index 672131deedb6ef..ab90eedf1e89c6 100644 --- a/lib/events.js +++ b/lib/events.js @@ -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 @@ -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) {