mirror of
https://github.com/zebrajr/node.git
synced 2026-01-15 12:15:26 +00:00
process: optimize asyncHandledRejections by using FixedQueue
PR-URL: https://github.com/nodejs/node/pull/60854 Reviewed-By: Juan José Arboleda <soyjuanarbol@gmail.com> Reviewed-By: Ilyas Shabi <ilyasshabi94@gmail.com> Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
This commit is contained in:
43
benchmark/process/handled-rejections.js
Normal file
43
benchmark/process/handled-rejections.js
Normal file
@@ -0,0 +1,43 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common.js');
|
||||
|
||||
// Benchmarks the throughput of processing many promise rejections that are
|
||||
// initially unhandled, get warned, and then handled asynchronously, exercising
|
||||
// asyncHandledRejections + processPromiseRejections.
|
||||
//
|
||||
// Note: This benchmark uses --unhandled-rejections=warn to avoid crashing
|
||||
// when promises are temporarily unhandled.
|
||||
|
||||
const bench = common.createBenchmark(main, {
|
||||
n: [1e4, 5e4, 1e5],
|
||||
}, {
|
||||
flags: ['--unhandled-rejections=warn'],
|
||||
});
|
||||
|
||||
function main({ n }) {
|
||||
const rejections = [];
|
||||
|
||||
// Suppress warning output during the benchmark
|
||||
process.removeAllListeners('warning');
|
||||
|
||||
for (let i = 0; i < n; i++) {
|
||||
rejections.push(Promise.reject(i));
|
||||
}
|
||||
|
||||
// Wait for them to be processed as unhandled and warned.
|
||||
setImmediate(() => {
|
||||
setImmediate(() => {
|
||||
bench.start();
|
||||
|
||||
for (let i = 0; i < n; i++) {
|
||||
rejections[i].catch(() => {});
|
||||
}
|
||||
|
||||
// Let processPromiseRejections drain asyncHandledRejections.
|
||||
setImmediate(() => {
|
||||
bench.end(n);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
'use strict';
|
||||
|
||||
const {
|
||||
ArrayPrototypePush,
|
||||
ArrayPrototypeShift,
|
||||
Error,
|
||||
ObjectPrototypeHasOwnProperty,
|
||||
SafeMap,
|
||||
SafeWeakMap,
|
||||
} = primordials;
|
||||
|
||||
const FixedQueue = require('internal/fixed_queue');
|
||||
|
||||
const {
|
||||
tickInfo,
|
||||
promiseRejectEvents: {
|
||||
@@ -119,9 +119,9 @@ const maybeUnhandledPromises = new SafeWeakMap();
|
||||
let pendingUnhandledRejections = new SafeMap();
|
||||
|
||||
/**
|
||||
* @type {Array<{promise: Promise, warning: Error}>}
|
||||
* @type {import('internal/fixed_queue')<{promise: Promise, warning: Error}>}
|
||||
*/
|
||||
const asyncHandledRejections = [];
|
||||
const asyncHandledRejections = new FixedQueue();
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
@@ -219,7 +219,7 @@ function handledRejection(promise) {
|
||||
if (promiseInfo.warned) {
|
||||
// Generate the warning object early to get a good stack trace.
|
||||
const warning = new PromiseRejectionHandledWarning(promiseInfo.uid);
|
||||
ArrayPrototypePush(asyncHandledRejections, { promise, warning });
|
||||
asyncHandledRejections.push({ promise, warning });
|
||||
setHasRejectionToWarn(true);
|
||||
}
|
||||
}
|
||||
@@ -375,10 +375,10 @@ function getUnhandledRejectionsMode() {
|
||||
// a warning to be emitted which requires the microtask and next tick
|
||||
// queues to be drained again.
|
||||
function processPromiseRejections() {
|
||||
let maybeScheduledTicksOrMicrotasks = asyncHandledRejections.length > 0;
|
||||
let maybeScheduledTicksOrMicrotasks = !asyncHandledRejections.isEmpty();
|
||||
|
||||
while (asyncHandledRejections.length !== 0) {
|
||||
const { promise, warning } = ArrayPrototypeShift(asyncHandledRejections);
|
||||
while (!asyncHandledRejections.isEmpty()) {
|
||||
const { promise, warning } = asyncHandledRejections.shift();
|
||||
if (!process.emit('rejectionHandled', promise)) {
|
||||
process.emitWarning(warning);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user