Skip to content

Commit 012bf70

Browse files
authored
process: optimize asyncHandledRejections by using FixedQueue
PR-URL: #60854 Reviewed-By: Juan José Arboleda <soyjuanarbol@gmail.com> Reviewed-By: Ilyas Shabi <ilyasshabi94@gmail.com> Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
1 parent 0457bfe commit 012bf70

2 files changed

Lines changed: 51 additions & 8 deletions

File tree

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
'use strict';
2+
3+
constcommon=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+
constbench=common.createBenchmark(main,{
13+
n: [1e4,5e4,1e5],
14+
},{
15+
flags: ['--unhandled-rejections=warn'],
16+
});
17+
18+
functionmain({ n }){
19+
constrejections=[];
20+
21+
// Suppress warning output during the benchmark
22+
process.removeAllListeners('warning');
23+
24+
for(leti=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(leti=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+
constFixedQueue=require('internal/fixed_queue');
11+
1212
const{
1313
tickInfo,
1414
promiseRejectEvents: {
@@ -119,9 +119,9 @@ const maybeUnhandledPromises = new SafeWeakMap();
119119
letpendingUnhandledRejections=newSafeMap();
120120

121121
/**
122-
* @type {Array<{promise: Promise, warning: Error}>}
122+
* @type {import('internal/fixed_queue')<{promise: Promise, warning: Error}>}
123123
*/
124-
constasyncHandledRejections=[];
124+
constasyncHandledRejections=newFixedQueue();
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
constwarning=newPromiseRejectionHandledWarning(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
functionprocessPromiseRejections(){
378-
letmaybeScheduledTicksOrMicrotasks=asyncHandledRejections.length>0;
378+
letmaybeScheduledTicksOrMicrotasks=!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)