Skip to content

Commit f44f18a

Browse files
committed
events: remove emit micro-optimizations
With improvements in V8, using separate emit functions is no longer necessary and can instead be replaced by the spread operator. improvement confidence p.value events/ee-emit.js n=2000000 2.98 % 0.09852489 events/ee-emit-2-args.js n=2000000 4.19 % *** 0.0001914216 events/ee-emit-6-args.js n=2000000 61.69 % *** 6.611964e-35 events/ee-emit-diff-args.js n=2000000 -0.36 % 0.305069 events/ee-once.js n=20000000 6.42 % *** 1.27831e-06 PR-URL: #16869 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Refael Ackermann <[email protected]> Reviewed-By: Evan Lucas <[email protected]> Reviewed-By: Bryan English <[email protected]> Reviewed-By: Luigi Pinca <[email protected]> Reviewed-By: Timothy Gu <[email protected]> Reviewed-By: Franziska Hinkelmann <[email protected]> Reviewed-By: Benedikt Meurer <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Brian White <[email protected]>
1 parent 6b351e9 commit f44f18a

File tree

4 files changed

+51
-117
lines changed

4 files changed

+51
-117
lines changed

benchmark/events/ee-emit-multi-args.js

Lines changed: 0 additions & 20 deletions
This file was deleted.

benchmark/events/ee-emit.js

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,51 @@
22
const common = require('../common.js');
33
const EventEmitter = require('events').EventEmitter;
44

5-
const bench = common.createBenchmark(main, { n: [2e6] });
5+
const bench = common.createBenchmark(main, {
6+
n: [2e6],
7+
argc: [0, 2, 4, 10],
8+
listeners: [1, 5, 10],
9+
});
610

711
function main(conf) {
812
const n = conf.n | 0;
13+
const argc = conf.argc | 0;
14+
const listeners = Math.max(conf.listeners | 0, 1);
915

1016
const ee = new EventEmitter();
1117

12-
for (var k = 0; k < 10; k += 1)
18+
for (var k = 0; k < listeners; k += 1)
1319
ee.on('dummy', function() {});
1420

15-
bench.start();
16-
for (var i = 0; i < n; i += 1) {
17-
ee.emit('dummy');
21+
var i;
22+
switch (argc) {
23+
case 2:
24+
bench.start();
25+
for (i = 0; i < n; i += 1) {
26+
ee.emit('dummy', true, 5);
27+
}
28+
bench.end(n);
29+
break;
30+
case 4:
31+
bench.start();
32+
for (i = 0; i < n; i += 1) {
33+
ee.emit('dummy', true, 5, 10, false);
34+
}
35+
bench.end(n);
36+
break;
37+
case 10:
38+
bench.start();
39+
for (i = 0; i < n; i += 1) {
40+
ee.emit('dummy', true, 5, 10, false, 5, 'string', true, false, 11, 20);
41+
}
42+
bench.end(n);
43+
break;
44+
default:
45+
bench.start();
46+
for (i = 0; i < n; i += 1) {
47+
ee.emit('dummy');
48+
}
49+
bench.end(n);
50+
break;
1851
}
19-
bench.end(n);
2052
}

lib/events.js

Lines changed: 9 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -105,63 +105,6 @@ EventEmitter.prototype.getMaxListeners = function getMaxListeners() {
105105
return $getMaxListeners(this);
106106
};
107107

108-
// These standalone emit* functions are used to optimize calling of event
109-
// handlers for fast cases because emit() itself often has a variable number of
110-
// arguments and can be deoptimized because of that. These functions always have
111-
// the same number of arguments and thus do not get deoptimized, so the code
112-
// inside them can execute faster.
113-
function emitNone(handler, isFn, self) {
114-
if (isFn)
115-
handler.call(self);
116-
else {
117-
var len = handler.length;
118-
var listeners = arrayClone(handler, len);
119-
for (var i = 0; i < len; ++i)
120-
listeners[i].call(self);
121-
}
122-
}
123-
function emitOne(handler, isFn, self, arg1) {
124-
if (isFn)
125-
handler.call(self, arg1);
126-
else {
127-
var len = handler.length;
128-
var listeners = arrayClone(handler, len);
129-
for (var i = 0; i < len; ++i)
130-
listeners[i].call(self, arg1);
131-
}
132-
}
133-
function emitTwo(handler, isFn, self, arg1, arg2) {
134-
if (isFn)
135-
handler.call(self, arg1, arg2);
136-
else {
137-
var len = handler.length;
138-
var listeners = arrayClone(handler, len);
139-
for (var i = 0; i < len; ++i)
140-
listeners[i].call(self, arg1, arg2);
141-
}
142-
}
143-
function emitThree(handler, isFn, self, arg1, arg2, arg3) {
144-
if (isFn)
145-
handler.call(self, arg1, arg2, arg3);
146-
else {
147-
var len = handler.length;
148-
var listeners = arrayClone(handler, len);
149-
for (var i = 0; i < len; ++i)
150-
listeners[i].call(self, arg1, arg2, arg3);
151-
}
152-
}
153-
154-
function emitMany(handler, isFn, self, args) {
155-
if (isFn)
156-
handler.apply(self, args);
157-
else {
158-
var len = handler.length;
159-
var listeners = arrayClone(handler, len);
160-
for (var i = 0; i < len; ++i)
161-
listeners[i].apply(self, args);
162-
}
163-
}
164-
165108
EventEmitter.prototype.emit = function emit(type, ...args) {
166109
let doError = (type === 'error');
167110

@@ -212,22 +155,13 @@ EventEmitter.prototype.emit = function emit(type, ...args) {
212155
needDomainExit = true;
213156
}
214157

215-
const isFn = typeof handler === 'function';
216-
switch (args.length) {
217-
case 0:
218-
emitNone(handler, isFn, this);
219-
break;
220-
case 1:
221-
emitOne(handler, isFn, this, args[0]);
222-
break;
223-
case 2:
224-
emitTwo(handler, isFn, this, args[0], args[1]);
225-
break;
226-
case 3:
227-
emitThree(handler, isFn, this, args[0], args[1], args[2]);
228-
break;
229-
default:
230-
emitMany(handler, isFn, this, args);
158+
if (typeof handler === 'function') {
159+
handler.apply(this, args);
160+
} else {
161+
const len = handler.length;
162+
const listeners = arrayClone(handler, len);
163+
for (var i = 0; i < len; ++i)
164+
listeners[i].apply(this, args);
231165
}
232166

233167
if (needDomainExit)
@@ -313,23 +247,11 @@ EventEmitter.prototype.prependListener =
313247
return _addListener(this, type, listener, true);
314248
};
315249

316-
function onceWrapper() {
250+
function onceWrapper(...args) {
317251
if (!this.fired) {
318252
this.target.removeListener(this.type, this.wrapFn);
319253
this.fired = true;
320-
switch (arguments.length) {
321-
case 0:
322-
return this.listener.call(this.target);
323-
case 1:
324-
return this.listener.call(this.target, arguments[0]);
325-
case 2:
326-
return this.listener.call(this.target, arguments[0], arguments[1]);
327-
case 3:
328-
return this.listener.call(this.target, arguments[0], arguments[1],
329-
arguments[2]);
330-
default:
331-
this.listener.apply(this.target, arguments);
332-
}
254+
this.listener.apply(this.target, args);
333255
}
334256
}
335257

test/message/stdin_messages.out

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ SyntaxError: Strict mode code may not include a with statement
99
at Module._compile (module.js:*:*)
1010
at evalScript (bootstrap_node.js:*:*)
1111
at Socket.<anonymous> (bootstrap_node.js:*:*)
12-
at emitNone (events.js:*:*)
1312
at Socket.emit (events.js:*:*)
1413
at endReadableNT (_stream_readable.js:*:*)
1514
at _combinedTickCallback (internal/process/next_tick.js:*:*)
15+
at process._tickCallback (internal/process/next_tick.js:*:*)
1616
42
1717
42
1818
[stdin]:1
@@ -27,9 +27,9 @@ Error: hello
2727
at Module._compile (module.js:*:*)
2828
at evalScript (bootstrap_node.js:*:*)
2929
at Socket.<anonymous> (bootstrap_node.js:*:*)
30-
at emitNone (events.js:*:*)
3130
at Socket.emit (events.js:*:*)
3231
at endReadableNT (_stream_readable.js:*:*)
32+
at _combinedTickCallback (internal/process/next_tick.js:*:*)
3333
[stdin]:1
3434
throw new Error("hello")
3535
^
@@ -42,9 +42,9 @@ Error: hello
4242
at Module._compile (module.js:*:*)
4343
at evalScript (bootstrap_node.js:*:*)
4444
at Socket.<anonymous> (bootstrap_node.js:*:*)
45-
at emitNone (events.js:*:*)
4645
at Socket.emit (events.js:*:*)
4746
at endReadableNT (_stream_readable.js:*:*)
47+
at _combinedTickCallback (internal/process/next_tick.js:*:*)
4848
100
4949
[stdin]:1
5050
var x = 100; y = x;
@@ -58,9 +58,9 @@ ReferenceError: y is not defined
5858
at Module._compile (module.js:*:*)
5959
at evalScript (bootstrap_node.js:*:*)
6060
at Socket.<anonymous> (bootstrap_node.js:*:*)
61-
at emitNone (events.js:*:*)
6261
at Socket.emit (events.js:*:*)
6362
at endReadableNT (_stream_readable.js:*:*)
63+
at _combinedTickCallback (internal/process/next_tick.js:*:*)
6464

6565
[stdin]:1
6666
var ______________________________________________; throw 10

0 commit comments

Comments
 (0)