Skip to content

Commit b63ee89

Browse files
gurgundayaduh95
authored andcommitted
process: optimize asyncHandledRejections by using FixedQueue
1 parent 42d0e13 commit b63ee89

File tree

2 files changed

+51
-8
lines changed

2 files changed

+51
-8
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
'use strict';
2+
3+
const common = require('../common.js');
4+
5+
// Benchmarks the throughput of processing many promise rejections that are
6+
// initially unhandled, get warned, and then handled asynchronously, exercising
7+
// asyncHandledRejections + processPromiseRejections.
8+
//
9+
// Note: This benchmark uses --unhandled-rejections=warn to avoid crashing
10+
// when promises are temporarily unhandled.
11+
12+
const bench = common.createBenchmark(main, {
13+
n: [1e4, 5e4, 1e5],
14+
}, {
15+
flags: ['--unhandled-rejections=warn'],
16+
});
17+
18+
function main({ n }) {
19+
const rejections = [];
20+
21+
// Suppress warning output during the benchmark
22+
process.removeAllListeners('warning');
23+
24+
for (let i = 0; i < n; i++) {
25+
rejections.push(Promise.reject(i));
26+
}
27+
28+
// Wait for them to be processed as unhandled and warned.
29+
setImmediate(() => {
30+
setImmediate(() => {
31+
bench.start();
32+
33+
for (let i = 0; i < n; i++) {
34+
rejections[i].catch(() => {});
35+
}
36+
37+
// Let processPromiseRejections drain asyncHandledRejections.
38+
setImmediate(() => {
39+
bench.end(n);
40+
});
41+
});
42+
});
43+
}

lib/internal/process/promises.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
'use strict';
22

33
const {
4-
ArrayPrototypePush,
5-
ArrayPrototypeShift,
64
Error,
75
ObjectPrototypeHasOwnProperty,
86
SafeMap,
97
SafeWeakMap,
108
} = primordials;
119

10+
const FixedQueue = require('internal/fixed_queue');
11+
1212
const {
1313
tickInfo,
1414
promiseRejectEvents: {
@@ -119,9 +119,9 @@ const maybeUnhandledPromises = new SafeWeakMap();
119119
let pendingUnhandledRejections = new SafeMap();
120120

121121
/**
122-
* @type {Array<{promise: Promise, warning: Error}>}
122+
* @type {import('internal/fixed_queue')<{promise: Promise, warning: Error}>}
123123
*/
124-
const asyncHandledRejections = [];
124+
const asyncHandledRejections = new FixedQueue();
125125

126126
/**
127127
* @type {number}
@@ -219,7 +219,7 @@ function handledRejection(promise) {
219219
if (promiseInfo.warned) {
220220
// Generate the warning object early to get a good stack trace.
221221
const warning = new PromiseRejectionHandledWarning(promiseInfo.uid);
222-
ArrayPrototypePush(asyncHandledRejections, { promise, warning });
222+
asyncHandledRejections.push({ promise, warning });
223223
setHasRejectionToWarn(true);
224224
}
225225
}
@@ -375,10 +375,10 @@ function getUnhandledRejectionsMode() {
375375
// a warning to be emitted which requires the microtask and next tick
376376
// queues to be drained again.
377377
function processPromiseRejections() {
378-
let maybeScheduledTicksOrMicrotasks = asyncHandledRejections.length > 0;
378+
let maybeScheduledTicksOrMicrotasks = !asyncHandledRejections.isEmpty();
379379

380-
while (asyncHandledRejections.length !== 0) {
381-
const { promise, warning } = ArrayPrototypeShift(asyncHandledRejections);
380+
while (!asyncHandledRejections.isEmpty()) {
381+
const { promise, warning } = asyncHandledRejections.shift();
382382
if (!process.emit('rejectionHandled', promise)) {
383383
process.emitWarning(warning);
384384
}

0 commit comments

Comments
 (0)