Skip to content

Commit

Permalink
process: improve queueMicrotask performance
Browse files Browse the repository at this point in the history
Optimize the hot code paths of queueMicrotask by
not creating unnecessary objects, not looking up
properties on frozen primordials, etc.

PR-URL: nodejs#28093
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
  • Loading branch information
apapirovski committed Jun 10, 2019
1 parent 5bad514 commit cde3928
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 16 deletions.
26 changes: 15 additions & 11 deletions lib/async_hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,15 +134,16 @@ class AsyncResource {
constructor(type, opts = {}) {
validateString(type, 'type');

if (typeof opts === 'number') {
opts = { triggerAsyncId: opts, requireManualDestroy: false };
} else if (opts.triggerAsyncId === undefined) {
opts.triggerAsyncId = getDefaultTriggerAsyncId();
let triggerAsyncId = opts;
let requireManualDestroy = false;
if (typeof opts !== 'number') {
triggerAsyncId = opts.triggerAsyncId === undefined ?
getDefaultTriggerAsyncId() : opts.triggerAsyncId;
requireManualDestroy = !!opts.requireManualDestroy;
}

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

// This prop name (destroyed) has to be synchronized with C++
const destroyed = { destroyed: false };
this[destroyedSymbol] = destroyed;

if (initHooksExist()) {
emitInit(asyncId, type, triggerAsyncId, this);
}

if (!opts.requireManualDestroy) {
if (!requireManualDestroy) {
// This prop name (destroyed) has to be synchronized with C++
const destroyed = { destroyed: false };
this[destroyedSymbol] = destroyed;
registerDestroyHook(this, asyncId, destroyed);
}
}
Expand All @@ -168,14 +168,18 @@ class AsyncResource {
const asyncId = this[async_id_symbol];
emitBefore(asyncId, this[trigger_async_id_symbol]);
try {
if (thisArg === undefined)
return fn(...args);
return Reflect.apply(fn, thisArg, args);
} finally {
emitAfter(asyncId);
}
}

emitDestroy() {
this[destroyedSymbol].destroyed = true;
if (this[destroyedSymbol] !== undefined) {
this[destroyedSymbol].destroyed = true;
}
emitDestroy(this[async_id_symbol]);
return this;
}
Expand Down
8 changes: 3 additions & 5 deletions lib/internal/process/task_queues.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,15 +128,13 @@ function nextTick(callback) {
}

let AsyncResource;
const defaultMicrotaskResourceOpts = { requireManualDestroy: true };
function createMicrotaskResource() {
// Lazy load the async_hooks module
if (!AsyncResource) {
if (AsyncResource === undefined) {
AsyncResource = require('async_hooks').AsyncResource;
}
return new AsyncResource('Microtask', {
triggerAsyncId: getDefaultTriggerAsyncId(),
requireManualDestroy: true,
});
return new AsyncResource('Microtask', defaultMicrotaskResourceOpts);
}

function runMicrotask() {
Expand Down

0 comments on commit cde3928

Please sign in to comment.