Skip to content

Commit c291ce5

Browse files
mscdexcodebytere
authored andcommitted
events: improve arrayClone performance
PR-URL: #33774 Reviewed-By: Robert Nagy <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: Michaël Zasso <[email protected]> Reviewed-By: Zeyu Yang <[email protected]>
1 parent 499c740 commit c291ce5

File tree

4 files changed

+36
-37
lines changed

4 files changed

+36
-37
lines changed

benchmark/events/ee-emit.js

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const bench = common.createBenchmark(main, {
1010

1111
function main({ n, argc, listeners }) {
1212
const ee = new EventEmitter();
13+
ee.setMaxListeners(listeners + 1);
1314

1415
for (let k = 0; k < listeners; k += 1)
1516
ee.on('dummy', () => {});

benchmark/events/ee-listeners-many.js

-22
This file was deleted.

benchmark/events/ee-listeners.js

+22-8
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,34 @@
22
const common = require('../common.js');
33
const EventEmitter = require('events').EventEmitter;
44

5-
const bench = common.createBenchmark(main, { n: [5e6] });
5+
const bench = common.createBenchmark(main, {
6+
n: [5e6],
7+
listeners: [5, 50],
8+
raw: ['true', 'false']
9+
});
610

7-
function main({ n }) {
11+
function main({ n, listeners, raw }) {
812
const ee = new EventEmitter();
13+
ee.setMaxListeners(listeners * 2 + 1);
914

10-
for (let k = 0; k < 5; k += 1) {
15+
for (let k = 0; k < listeners; k += 1) {
1116
ee.on('dummy0', () => {});
1217
ee.on('dummy1', () => {});
1318
}
1419

15-
bench.start();
16-
for (let i = 0; i < n; i += 1) {
17-
const dummy = (i % 2 === 0) ? 'dummy0' : 'dummy1';
18-
ee.listeners(dummy);
20+
if (raw === 'true') {
21+
bench.start();
22+
for (let i = 0; i < n; i += 1) {
23+
const dummy = (i % 2 === 0) ? 'dummy0' : 'dummy1';
24+
ee.rawListeners(dummy);
25+
}
26+
bench.end(n);
27+
} else {
28+
bench.start();
29+
for (let i = 0; i < n; i += 1) {
30+
const dummy = (i % 2 === 0) ? 'dummy0' : 'dummy1';
31+
ee.listeners(dummy);
32+
}
33+
bench.end(n);
1934
}
20-
bench.end(n);
2135
}

lib/events.js

+13-7
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ EventEmitter.prototype.emit = function emit(type, ...args) {
322322
}
323323
} else {
324324
const len = handler.length;
325-
const listeners = arrayClone(handler, len);
325+
const listeners = arrayClone(handler);
326326
for (let i = 0; i < len; ++i) {
327327
const result = ReflectApply(listeners[i], this, args);
328328

@@ -560,7 +560,7 @@ function _listeners(target, type, unwrap) {
560560
return unwrap ? [evlistener.listener || evlistener] : [evlistener];
561561

562562
return unwrap ?
563-
unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length);
563+
unwrapListeners(evlistener) : arrayClone(evlistener);
564564
}
565565

566566
EventEmitter.prototype.listeners = function listeners(type) {
@@ -599,11 +599,17 @@ EventEmitter.prototype.eventNames = function eventNames() {
599599
return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : [];
600600
};
601601

602-
function arrayClone(arr, n) {
603-
const copy = new Array(n);
604-
for (let i = 0; i < n; ++i)
605-
copy[i] = arr[i];
606-
return copy;
602+
function arrayClone(arr) {
603+
// At least since V8 8.3, this implementation is faster than the previous
604+
// which always used a simple for-loop
605+
switch (arr.length) {
606+
case 2: return [arr[0], arr[1]];
607+
case 3: return [arr[0], arr[1], arr[2]];
608+
case 4: return [arr[0], arr[1], arr[2], arr[3]];
609+
case 5: return [arr[0], arr[1], arr[2], arr[3], arr[4]];
610+
case 6: return [arr[0], arr[1], arr[2], arr[3], arr[4], arr[5]];
611+
}
612+
return arr.slice();
607613
}
608614

609615
function unwrapListeners(arr) {

0 commit comments

Comments
 (0)