Browse Source

node: improve process.nextTick performance

Prevent deoptimization of process.nextTick by removing the try finally
block. This is not necessary as the next tick queue will be reset
anyway, no matter if the callback throws or not.

Use a predefined array size prevents resizing the array and is therefor
faster.

PR-URL: https://github.com/nodejs/node/pull/5092
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: James M Snell <jasnell@gmail.com>
process-exit-stdio-flushing
Ruben Bridgewater 9 years ago
committed by Trevor Norris
parent
commit
88307974e6
  1. 121
      src/node.js
  2. 8
      test/message/eval_messages.out
  3. 2
      test/message/nexttick_throw.out
  4. 8
      test/message/stdin_messages.out

121
src/node.js

@ -374,6 +374,26 @@
scheduleMicrotasks();
}
function _combinedTickCallback(args, callback) {
if (args === undefined) {
callback();
} else {
switch (args.length) {
case 1:
callback(args[0]);
break;
case 2:
callback(args[0], args[1]);
break;
case 3:
callback(args[0], args[1], args[2]);
break;
default:
callback.apply(null, args);
}
}
}
// Run callbacks that have no domain.
// Using domains will cause this to be overridden.
function _tickCallback() {
@ -384,27 +404,10 @@
tock = nextTickQueue[tickInfo[kIndex]++];
callback = tock.callback;
args = tock.args;
// Using separate callback execution functions helps to limit the
// scope of DEOPTs caused by using try blocks and allows direct
// Using separate callback execution functions allows direct
// callback invocation with small numbers of arguments to avoid the
// performance hit associated with using `fn.apply()`
if (args === undefined) {
nextTickCallbackWith0Args(callback);
} else {
switch (args.length) {
case 1:
nextTickCallbackWith1Arg(callback, args[0]);
break;
case 2:
nextTickCallbackWith2Args(callback, args[0], args[1]);
break;
case 3:
nextTickCallbackWith3Args(callback, args[0], args[1], args[2]);
break;
default:
nextTickCallbackWithManyArgs(callback, args);
}
}
_combinedTickCallback(args, callback);
if (1e4 < tickInfo[kIndex])
tickDone();
}
@ -425,27 +428,10 @@
args = tock.args;
if (domain)
domain.enter();
// Using separate callback execution functions helps to limit the
// scope of DEOPTs caused by using try blocks and allows direct
// Using separate callback execution functions allows direct
// callback invocation with small numbers of arguments to avoid the
// performance hit associated with using `fn.apply()`
if (args === undefined) {
nextTickCallbackWith0Args(callback);
} else {
switch (args.length) {
case 1:
nextTickCallbackWith1Arg(callback, args[0]);
break;
case 2:
nextTickCallbackWith2Args(callback, args[0], args[1]);
break;
case 3:
nextTickCallbackWith3Args(callback, args[0], args[1], args[2]);
break;
default:
nextTickCallbackWithManyArgs(callback, args);
}
}
_combinedTickCallback(args, callback);
if (1e4 < tickInfo[kIndex])
tickDone();
if (domain)
@ -457,61 +443,6 @@
} while (tickInfo[kLength] !== 0);
}
function nextTickCallbackWith0Args(callback) {
var threw = true;
try {
callback();
threw = false;
} finally {
if (threw)
tickDone();
}
}
function nextTickCallbackWith1Arg(callback, arg1) {
var threw = true;
try {
callback(arg1);
threw = false;
} finally {
if (threw)
tickDone();
}
}
function nextTickCallbackWith2Args(callback, arg1, arg2) {
var threw = true;
try {
callback(arg1, arg2);
threw = false;
} finally {
if (threw)
tickDone();
}
}
function nextTickCallbackWith3Args(callback, arg1, arg2, arg3) {
var threw = true;
try {
callback(arg1, arg2, arg3);
threw = false;
} finally {
if (threw)
tickDone();
}
}
function nextTickCallbackWithManyArgs(callback, args) {
var threw = true;
try {
callback.apply(null, args);
threw = false;
} finally {
if (threw)
tickDone();
}
}
function TickObject(c, args) {
this.callback = c;
this.domain = process.domain || null;
@ -527,9 +458,9 @@
var args;
if (arguments.length > 1) {
args = [];
args = new Array(arguments.length - 1);
for (var i = 1; i < arguments.length; i++)
args.push(arguments[i]);
args[i - 1] = arguments[i];
}
nextTickQueue.push(new TickObject(callback, args));

8
test/message/eval_messages.out

@ -7,7 +7,7 @@ SyntaxError: Strict mode code may not include a with statement
at Object.<anonymous> ([eval]-wrapper:*:*)
at Module._compile (module.js:*:*)
at node.js:*:*
at nextTickCallbackWith0Args (node.js:*:*)
at _combinedTickCallback (node.js:*:*)
at process._tickCallback (node.js:*:*)
42
42
@ -20,7 +20,7 @@ Error: hello
at Object.<anonymous> ([eval]-wrapper:*:*)
at Module._compile (module.js:*:*)
at node.js:*:*
at nextTickCallbackWith0Args (node.js:*:*)
at _combinedTickCallback (node.js:*:*)
at process._tickCallback (node.js:*:*)
[eval]:1
throw new Error("hello")
@ -31,7 +31,7 @@ Error: hello
at Object.<anonymous> ([eval]-wrapper:*:*)
at Module._compile (module.js:*:*)
at node.js:*:*
at nextTickCallbackWith0Args (node.js:*:*)
at _combinedTickCallback (node.js:*:*)
at process._tickCallback (node.js:*:*)
100
[eval]:1
@ -43,7 +43,7 @@ ReferenceError: y is not defined
at Object.<anonymous> ([eval]-wrapper:*:*)
at Module._compile (module.js:*:*)
at node.js:*:*
at nextTickCallbackWith0Args (node.js:*:*)
at _combinedTickCallback (node.js:*:*)
at process._tickCallback (node.js:*:*)
[eval]:1
var ______________________________________________; throw 10

2
test/message/nexttick_throw.out

@ -4,7 +4,7 @@
^
ReferenceError: undefined_reference_error_maker is not defined
at *test*message*nexttick_throw.js:*:*
at nextTickCallbackWith0Args (node.js:*:*)
at _combinedTickCallback (node.js:*:*)
at process._tickCallback (node.js:*:*)
at Function.Module.runMain (module.js:*:*)
at startup (node.js:*:*)

8
test/message/stdin_messages.out

@ -8,7 +8,7 @@ SyntaxError: Strict mode code may not include a with statement
at Object.<anonymous> ([stdin]-wrapper:*:*)
at Module._compile (module.js:*:*)
at node.js:*:*
at nextTickCallbackWith0Args (node.js:*:*)
at _combinedTickCallback (node.js:*:*)
at process._tickCallback (node.js:*:*)
42
42
@ -22,7 +22,7 @@ Error: hello
at Object.<anonymous> ([stdin]-wrapper:*:*)
at Module._compile (module.js:*:*)
at node.js:*:*
at nextTickCallbackWith0Args (node.js:*:*)
at _combinedTickCallback (node.js:*:*)
at process._tickCallback (node.js:*:*)
[stdin]:1
@ -34,7 +34,7 @@ Error: hello
at Object.<anonymous> ([stdin]-wrapper:*:*)
at Module._compile (module.js:*:*)
at node.js:*:*
at nextTickCallbackWith0Args (node.js:*:*)
at _combinedTickCallback (node.js:*:*)
at process._tickCallback (node.js:*:*)
100
@ -47,7 +47,7 @@ ReferenceError: y is not defined
at Object.<anonymous> ([stdin]-wrapper:*:*)
at Module._compile (module.js:*:*)
at node.js:*:*
at nextTickCallbackWith0Args (node.js:*:*)
at _combinedTickCallback (node.js:*:*)
at process._tickCallback (node.js:*:*)
[stdin]:1

Loading…
Cancel
Save