diff --git a/benchmark/process/queue-microtask-breadth.js b/benchmark/process/queue-microtask-breadth.js new file mode 100644 index 00000000000000..8bb33f6fdee6cc --- /dev/null +++ b/benchmark/process/queue-microtask-breadth.js @@ -0,0 +1,21 @@ +'use strict'; + +const common = require('../common.js'); +const bench = common.createBenchmark(main, { + n: [4e5] +}); + +function main({ n }) { + var j = 0; + + function cb() { + j++; + if (j === n) + bench.end(n); + } + + bench.start(); + for (var i = 0; i < n; i++) { + queueMicrotask(cb); + } +} diff --git a/benchmark/process/queue-microtask-depth.js b/benchmark/process/queue-microtask-depth.js new file mode 100644 index 00000000000000..407feb1b3270c4 --- /dev/null +++ b/benchmark/process/queue-microtask-depth.js @@ -0,0 +1,17 @@ +'use strict'; +const common = require('../common.js'); +const bench = common.createBenchmark(main, { + n: [12e5] +}); + +function main({ n }) { + let counter = n; + bench.start(); + queueMicrotask(onNextTick); + function onNextTick() { + if (--counter) + queueMicrotask(onNextTick); + else + bench.end(n); + } +} diff --git a/lib/internal/process/task_queues.js b/lib/internal/process/task_queues.js index 65ac0938022bd4..5f5ca5a0089cc7 100644 --- a/lib/internal/process/task_queues.js +++ b/lib/internal/process/task_queues.js @@ -37,6 +37,8 @@ const { } = require('internal/errors').codes; const FixedQueue = require('internal/fixed_queue'); +const FunctionBind = Function.call.bind(Function.prototype.bind); + // *Must* match Environment::TickInfo::Fields in src/env.h. const kHasTickScheduled = 0; @@ -149,28 +151,32 @@ function createMicrotaskResource() { }); } +function runMicrotask() { + this.runInAsyncScope(() => { + const callback = this.callback; + try { + callback(); + } catch (error) { + // TODO(devsnek) remove this if + // https://bugs.chromium.org/p/v8/issues/detail?id=8326 + // is resolved such that V8 triggers the fatal exception + // handler for microtasks + triggerFatalException(error); + } finally { + this.emitDestroy(); + } + }); +} + function queueMicrotask(callback) { if (typeof callback !== 'function') { throw new ERR_INVALID_ARG_TYPE('callback', 'function', callback); } const asyncResource = createMicrotaskResource(); + asyncResource.callback = callback; - enqueueMicrotask(() => { - asyncResource.runInAsyncScope(() => { - try { - callback(); - } catch (error) { - // TODO(devsnek) remove this if - // https://bugs.chromium.org/p/v8/issues/detail?id=8326 - // is resolved such that V8 triggers the fatal exception - // handler for microtasks - triggerFatalException(error); - } finally { - asyncResource.emitDestroy(); - } - }); - }); + enqueueMicrotask(FunctionBind(runMicrotask, asyncResource)); } module.exports = {