Skip to content

Commit 830574f

Browse files
mscdexaddaleax
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 1a09b4d commit 830574f

File tree

4 files changed

+36
-37
lines changed

4 files changed

+36
-37
lines changed

benchmark/events/ee-emit.js

Lines changed: 1 addition & 0 deletions
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

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

benchmark/events/ee-listeners.js

Lines changed: 22 additions & 8 deletions
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

Lines changed: 13 additions & 7 deletions
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

@@ -563,7 +563,7 @@ function _listeners(target, type, unwrap) {
563563
return unwrap ? [evlistener.listener || evlistener] : [evlistener];
564564

565565
return unwrap ?
566-
unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length);
566+
unwrapListeners(evlistener) : arrayClone(evlistener);
567567
}
568568

569569
EventEmitter.prototype.listeners = function listeners(type) {
@@ -602,11 +602,17 @@ EventEmitter.prototype.eventNames = function eventNames() {
602602
return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : [];
603603
};
604604

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

612618
function unwrapListeners(arr) {

0 commit comments

Comments
 (0)