diff --git a/benchmark/misc/set-immediate-breadth-args.js b/benchmark/misc/set-immediate-breadth-args.js new file mode 100644 index 00000000000000..6a904e2675d110 --- /dev/null +++ b/benchmark/misc/set-immediate-breadth-args.js @@ -0,0 +1,28 @@ +'use strict'; + +const common = require('../common.js'); +const bench = common.createBenchmark(main, { + millions: [5] +}); + +function main(conf) { + const N = +conf.millions * 1e6; + + process.on('exit', function() { + bench.end(N / 1e6); + }); + + function cb1(arg1) {} + function cb2(arg1, arg2) {} + function cb3(arg1, arg2, arg3) {} + + bench.start(); + for (let i = 0; i < N; i++) { + if (i % 3 === 0) + setImmediate(cb3, 512, true, null); + else if (i % 2 === 0) + setImmediate(cb2, false, 5.1); + else + setImmediate(cb1, 0); + } +} diff --git a/benchmark/misc/set-immediate-breadth.js b/benchmark/misc/set-immediate-breadth.js new file mode 100644 index 00000000000000..3d8b038342634d --- /dev/null +++ b/benchmark/misc/set-immediate-breadth.js @@ -0,0 +1,21 @@ +'use strict'; + +const common = require('../common.js'); +const bench = common.createBenchmark(main, { + millions: [10] +}); + +function main(conf) { + const N = +conf.millions * 1e6; + + process.on('exit', function() { + bench.end(N / 1e6); + }); + + function cb() {} + + bench.start(); + for (let i = 0; i < N; i++) { + setImmediate(cb); + } +} diff --git a/benchmark/misc/set-immediate-depth-args.js b/benchmark/misc/set-immediate-depth-args.js new file mode 100644 index 00000000000000..1f12ae6ec73fc0 --- /dev/null +++ b/benchmark/misc/set-immediate-depth-args.js @@ -0,0 +1,47 @@ +'use strict'; + +const common = require('../common.js'); +const bench = common.createBenchmark(main, { + millions: [10] +}); + +function main(conf) { + const N = +conf.millions * 1e6; + + process.on('exit', function() { + bench.end(N / 1e6); + }); + + function cb3(n, arg2, arg3) { + if (--n) { + if (n % 3 === 0) + setImmediate(cb3, n, true, null); + else if (n % 2 === 0) + setImmediate(cb2, n, 5.1); + else + setImmediate(cb1, n); + } + } + function cb2(n, arg2) { + if (--n) { + if (n % 3 === 0) + setImmediate(cb3, n, true, null); + else if (n % 2 === 0) + setImmediate(cb2, n, 5.1); + else + setImmediate(cb1, n); + } + } + function cb1(n) { + if (--n) { + if (n % 3 === 0) + setImmediate(cb3, n, true, null); + else if (n % 2 === 0) + setImmediate(cb2, n, 5.1); + else + setImmediate(cb1, n); + } + } + bench.start(); + setImmediate(cb1, N); +} diff --git a/benchmark/misc/set-immediate-depth.js b/benchmark/misc/set-immediate-depth.js new file mode 100644 index 00000000000000..12b9cdc7e6fd65 --- /dev/null +++ b/benchmark/misc/set-immediate-depth.js @@ -0,0 +1,22 @@ +'use strict'; + +const common = require('../common.js'); +const bench = common.createBenchmark(main, { + millions: [10] +}); + +function main(conf) { + const N = +conf.millions * 1e6; + let n = N; + + process.on('exit', function() { + bench.end(N / 1e6); + }); + + bench.start(); + setImmediate(onNextTick); + function onNextTick() { + if (--n) + setImmediate(onNextTick); + } +} diff --git a/lib/timers.js b/lib/timers.js index ee7c45aaed36d6..99010d424a984e 100644 --- a/lib/timers.js +++ b/lib/timers.js @@ -215,8 +215,8 @@ function listOnTimeout() { } -// An optimization so that the try/finally only de-optimizes what is in this -// smaller function. +// An optimization so that the try/finally only de-optimizes (since at least v8 +// 4.7) what is in this smaller function. function tryOnTimeout(timer, list) { timer._called = true; var threw = true; @@ -520,23 +520,7 @@ function processImmediate() { if (domain) domain.enter(); - var threw = true; - try { - immediate._onImmediate(); - threw = false; - } finally { - if (threw) { - if (!L.isEmpty(queue)) { - // Handle any remaining on next tick, assuming we're still - // alive to do so. - while (!L.isEmpty(immediateQueue)) { - L.append(queue, L.shift(immediateQueue)); - } - immediateQueue = queue; - process.nextTick(processImmediate); - } - } - } + tryOnImmediate(immediate, queue); if (domain) domain.exit(); @@ -551,6 +535,26 @@ function processImmediate() { } +// An optimization so that the try/finally only de-optimizes (since at least v8 +// 4.7) what is in this smaller function. +function tryOnImmediate(immediate, queue) { + var threw = true; + try { + immediate._onImmediate(); + threw = false; + } finally { + if (threw && !L.isEmpty(queue)) { + // Handle any remaining on next tick, assuming we're still alive to do so. + while (!L.isEmpty(immediateQueue)) { + L.append(queue, L.shift(immediateQueue)); + } + immediateQueue = queue; + process.nextTick(processImmediate); + } + } +} + + function Immediate() { } Immediate.prototype.domain = undefined;