Skip to content

Commit b491eab

Browse files
apapirovskiBridgeAR
authored andcommitted
process: improve queueMicrotask performance
Optimize the hot code paths of queueMicrotask by not creating unnecessary objects, not looking up properties on frozen primordials, etc. PR-URL: #28093 Reviewed-By: Ruben Bridgewater <[email protected]> Reviewed-By: Gus Caplan <[email protected]> Reviewed-By: Matteo Collina <[email protected]>
1 parent 3f1787b commit b491eab

File tree

2 files changed

+18
-16
lines changed

2 files changed

+18
-16
lines changed

lib/async_hooks.js

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -134,15 +134,16 @@ class AsyncResource {
134134
constructor(type, opts = {}) {
135135
validateString(type, 'type');
136136

137-
if (typeof opts === 'number') {
138-
opts = { triggerAsyncId: opts, requireManualDestroy: false };
139-
} else if (opts.triggerAsyncId === undefined) {
140-
opts.triggerAsyncId = getDefaultTriggerAsyncId();
137+
let triggerAsyncId = opts;
138+
let requireManualDestroy = false;
139+
if (typeof opts !== 'number') {
140+
triggerAsyncId = opts.triggerAsyncId === undefined ?
141+
getDefaultTriggerAsyncId() : opts.triggerAsyncId;
142+
requireManualDestroy = !!opts.requireManualDestroy;
141143
}
142144

143145
// Unlike emitInitScript, AsyncResource doesn't supports null as the
144146
// triggerAsyncId.
145-
const triggerAsyncId = opts.triggerAsyncId;
146147
if (!Number.isSafeInteger(triggerAsyncId) || triggerAsyncId < -1) {
147148
throw new ERR_INVALID_ASYNC_ID('triggerAsyncId', triggerAsyncId);
148149
}
@@ -151,15 +152,14 @@ class AsyncResource {
151152
this[async_id_symbol] = asyncId;
152153
this[trigger_async_id_symbol] = triggerAsyncId;
153154

154-
// This prop name (destroyed) has to be synchronized with C++
155-
const destroyed = { destroyed: false };
156-
this[destroyedSymbol] = destroyed;
157-
158155
if (initHooksExist()) {
159156
emitInit(asyncId, type, triggerAsyncId, this);
160157
}
161158

162-
if (!opts.requireManualDestroy) {
159+
if (!requireManualDestroy) {
160+
// This prop name (destroyed) has to be synchronized with C++
161+
const destroyed = { destroyed: false };
162+
this[destroyedSymbol] = destroyed;
163163
registerDestroyHook(this, asyncId, destroyed);
164164
}
165165
}
@@ -168,14 +168,18 @@ class AsyncResource {
168168
const asyncId = this[async_id_symbol];
169169
emitBefore(asyncId, this[trigger_async_id_symbol]);
170170
try {
171+
if (thisArg === undefined)
172+
return fn(...args);
171173
return Reflect.apply(fn, thisArg, args);
172174
} finally {
173175
emitAfter(asyncId);
174176
}
175177
}
176178

177179
emitDestroy() {
178-
this[destroyedSymbol].destroyed = true;
180+
if (this[destroyedSymbol] !== undefined) {
181+
this[destroyedSymbol].destroyed = true;
182+
}
179183
emitDestroy(this[async_id_symbol]);
180184
return this;
181185
}

lib/internal/process/task_queues.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,15 +128,13 @@ function nextTick(callback) {
128128
}
129129

130130
let AsyncResource;
131+
const defaultMicrotaskResourceOpts = { requireManualDestroy: true };
131132
function createMicrotaskResource() {
132133
// Lazy load the async_hooks module
133-
if (!AsyncResource) {
134+
if (AsyncResource === undefined) {
134135
AsyncResource = require('async_hooks').AsyncResource;
135136
}
136-
return new AsyncResource('Microtask', {
137-
triggerAsyncId: getDefaultTriggerAsyncId(),
138-
requireManualDestroy: true,
139-
});
137+
return new AsyncResource('Microtask', defaultMicrotaskResourceOpts);
140138
}
141139

142140
function runMicrotask() {

0 commit comments

Comments
 (0)