timers: improve setImmediate() performance
This commit improves setImmediate() performance by moving the try-finally block that wraps callback execution into a separate function because currently v8 never tries to optimize functions that contain try-finally blocks. With this change, there is a ~20-40% improvement in the included setImmediate() depth benchmarks. The breadth benchmarks show a slight improvement. PR-URL: https://github.com/nodejs/node/pull/4169 Reviewed-By: Minwoo Jung <jmwsoft@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
This commit is contained in:
parent
ad8257fa5b
commit
089bef0a81
28
benchmark/misc/set-immediate-breadth-args.js
Normal file
28
benchmark/misc/set-immediate-breadth-args.js
Normal file
@ -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);
|
||||
}
|
||||
}
|
21
benchmark/misc/set-immediate-breadth.js
Normal file
21
benchmark/misc/set-immediate-breadth.js
Normal file
@ -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);
|
||||
}
|
||||
}
|
47
benchmark/misc/set-immediate-depth-args.js
Normal file
47
benchmark/misc/set-immediate-depth-args.js
Normal file
@ -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);
|
||||
}
|
22
benchmark/misc/set-immediate-depth.js
Normal file
22
benchmark/misc/set-immediate-depth.js
Normal file
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user