Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 9d65724

Browse filesBrowse files
apapirovskiMylesBorins
authored andcommitted
process: slightly simplify next tick execution
Get rid of separate function to call callback from _tickCallback as it no longer yields worthwhile performance improvement. Move some code from nextTick & internalNextTick into TickObject constructor to minimize duplication. PR-URL: #16888 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Refael Ackermann <refack@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Timothy Gu <timothygu99@gmail.com>
1 parent 5736dc4 commit 9d65724
Copy full SHA for 9d65724

File tree

Expand file treeCollapse file tree

8 files changed

+81
-53
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

8 files changed

+81
-53
lines changed
Open diff view settings
Collapse file

‎benchmark/process/next-tick-breadth-args.js‎

Copy file name to clipboardExpand all lines: benchmark/process/next-tick-breadth-args.js
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
const common = require('../common.js');
44
const bench = common.createBenchmark(main, {
5-
millions: [2]
5+
millions: [4]
66
});
77

88
function main(conf) {
Collapse file

‎benchmark/process/next-tick-breadth.js‎

Copy file name to clipboardExpand all lines: benchmark/process/next-tick-breadth.js
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
const common = require('../common.js');
44
const bench = common.createBenchmark(main, {
5-
millions: [2]
5+
millions: [4]
66
});
77

88
function main(conf) {
Collapse file
+25Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
'use strict';
2+
const common = require('../common.js');
3+
const bench = common.createBenchmark(main, {
4+
millions: [5]
5+
});
6+
7+
function main(conf) {
8+
var n = +conf.millions * 1e6;
9+
10+
bench.start();
11+
for (var i = 0; i < n; i++) {
12+
if (i % 4 === 0)
13+
process.nextTick(onNextTick, i, true, 10, 'test');
14+
else if (i % 3 === 0)
15+
process.nextTick(onNextTick, i, true, 10);
16+
else if (i % 2 === 0)
17+
process.nextTick(onNextTick, i, 20);
18+
else
19+
process.nextTick(onNextTick, i);
20+
}
21+
function onNextTick(i) {
22+
if (i + 1 === n)
23+
bench.end(+conf.millions);
24+
}
25+
}
Collapse file
+18Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
'use strict';
2+
const common = require('../common.js');
3+
const bench = common.createBenchmark(main, {
4+
millions: [5]
5+
});
6+
7+
function main(conf) {
8+
var n = +conf.millions * 1e6;
9+
10+
bench.start();
11+
for (var i = 0; i < n; i++) {
12+
process.nextTick(onNextTick, i);
13+
}
14+
function onNextTick(i) {
15+
if (i + 1 === n)
16+
bench.end(+conf.millions);
17+
}
18+
}
Collapse file

‎lib/internal/process/next_tick.js‎

Copy file name to clipboardExpand all lines: lib/internal/process/next_tick.js
+33-44Lines changed: 33 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ function setupNextTick() {
6060
// Grab the constants necessary for working with internal arrays.
6161
const { kInit, kDestroy, kAsyncIdCounter } = async_wrap.constants;
6262
const { async_id_symbol, trigger_async_id_symbol } = async_wrap;
63-
var nextTickQueue = new NextTickQueue();
63+
const nextTickQueue = new NextTickQueue();
6464
var microtasksScheduled = false;
6565

6666
// Used to run V8's micro task queue.
@@ -99,7 +99,6 @@ function setupNextTick() {
9999
const microTasksTickObject = {
100100
callback: runMicrotasksCallback,
101101
args: undefined,
102-
domain: null,
103102
[async_id_symbol]: 0,
104103
[trigger_async_id_symbol]: 0
105104
};
@@ -125,35 +124,13 @@ function setupNextTick() {
125124
}
126125
}
127126

128-
function _combinedTickCallback(args, callback) {
129-
if (args === undefined) {
130-
callback();
131-
} else {
132-
switch (args.length) {
133-
case 1:
134-
callback(args[0]);
135-
break;
136-
case 2:
137-
callback(args[0], args[1]);
138-
break;
139-
case 3:
140-
callback(args[0], args[1], args[2]);
141-
break;
142-
default:
143-
callback(...args);
144-
}
145-
}
146-
}
147-
148127
// Run callbacks that have no domain.
149128
// Using domains will cause this to be overridden.
150129
function _tickCallback() {
151130
do {
152131
while (tickInfo[kIndex] < tickInfo[kLength]) {
153132
++tickInfo[kIndex];
154133
const tock = nextTickQueue.shift();
155-
const callback = tock.callback;
156-
const args = tock.args;
157134

158135
// CHECK(Number.isSafeInteger(tock[async_id_symbol]))
159136
// CHECK(tock[async_id_symbol] > 0)
@@ -173,10 +150,11 @@ function setupNextTick() {
173150
if (async_hook_fields[kDestroy] > 0)
174151
emitDestroy(tock[async_id_symbol]);
175152

176-
// Using separate callback execution functions allows direct
177-
// callback invocation with small numbers of arguments to avoid the
178-
// performance hit associated with using `fn.apply()`
179-
_combinedTickCallback(args, callback);
153+
const callback = tock.callback;
154+
if (tock.args === undefined)
155+
callback();
156+
else
157+
Reflect.apply(callback, undefined, tock.args);
180158

181159
emitAfter(tock[async_id_symbol]);
182160

@@ -191,11 +169,21 @@ function setupNextTick() {
191169

192170
class TickObject {
193171
constructor(callback, args, asyncId, triggerAsyncId) {
172+
// this must be set to null first to avoid function tracking
173+
// on the hidden class, revisit in V8 versions after 6.2
174+
this.callback = null;
194175
this.callback = callback;
195176
this.args = args;
196-
this.domain = process.domain || null;
177+
197178
this[async_id_symbol] = asyncId;
198179
this[trigger_async_id_symbol] = triggerAsyncId;
180+
181+
if (async_hook_fields[kInit] > 0) {
182+
emitInit(asyncId,
183+
'TickObject',
184+
triggerAsyncId,
185+
this);
186+
}
199187
}
200188
}
201189

@@ -220,13 +208,14 @@ function setupNextTick() {
220208
args[i - 1] = arguments[i];
221209
}
222210

223-
const asyncId = ++async_id_fields[kAsyncIdCounter];
224-
const triggerAsyncId = initTriggerId();
225-
const obj = new TickObject(callback, args, asyncId, triggerAsyncId);
226-
nextTickQueue.push(obj);
211+
// In V8 6.2, moving tickInfo & async_id_fields[kAsyncIdCounter] into the
212+
// TickObject incurs a significant performance penalty in the
213+
// next-tick-breadth-args benchmark (revisit later)
227214
++tickInfo[kLength];
228-
if (async_hook_fields[kInit] > 0)
229-
emitInit(asyncId, 'TickObject', triggerAsyncId, obj);
215+
nextTickQueue.push(new TickObject(callback,
216+
args,
217+
++async_id_fields[kAsyncIdCounter],
218+
initTriggerId()));
230219
}
231220

232221
// `internalNextTick()` will not enqueue any callback when the process is
@@ -240,10 +229,6 @@ function setupNextTick() {
240229
if (process._exiting)
241230
return;
242231

243-
if (triggerAsyncId === null) {
244-
triggerAsyncId = async_hooks.initTriggerId();
245-
}
246-
247232
var args;
248233
switch (arguments.length) {
249234
case 2: break;
@@ -256,11 +241,15 @@ function setupNextTick() {
256241
args[i - 2] = arguments[i];
257242
}
258243

259-
const asyncId = ++async_id_fields[kAsyncIdCounter];
260-
const obj = new TickObject(callback, args, asyncId, triggerAsyncId);
261-
nextTickQueue.push(obj);
244+
if (triggerAsyncId === null)
245+
triggerAsyncId = initTriggerId();
246+
// In V8 6.2, moving tickInfo & async_id_fields[kAsyncIdCounter] into the
247+
// TickObject incurs a significant performance penalty in the
248+
// next-tick-breadth-args benchmark (revisit later)
262249
++tickInfo[kLength];
263-
if (async_hook_fields[kInit] > 0)
264-
emitInit(asyncId, 'TickObject', triggerAsyncId, obj);
250+
nextTickQueue.push(new TickObject(callback,
251+
args,
252+
++async_id_fields[kAsyncIdCounter],
253+
triggerAsyncId));
265254
}
266255
}
Collapse file

‎test/message/nexttick_throw.out‎

Copy file name to clipboardExpand all lines: test/message/nexttick_throw.out
-1Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
^
55
ReferenceError: undefined_reference_error_maker is not defined
66
at *test*message*nexttick_throw.js:*:*
7-
at _combinedTickCallback (internal/process/next_tick.js:*:*)
87
at process._tickCallback (internal/process/next_tick.js:*:*)
98
at Function.Module.runMain (module.js:*:*)
109
at startup (bootstrap_node.js:*:*)
Collapse file

‎test/message/stdin_messages.out‎

Copy file name to clipboardExpand all lines: test/message/stdin_messages.out
+3-4Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ SyntaxError: Strict mode code may not include a with statement
1111
at Socket.<anonymous> (bootstrap_node.js:*:*)
1212
at Socket.emit (events.js:*:*)
1313
at endReadableNT (_stream_readable.js:*:*)
14-
at _combinedTickCallback (internal/process/next_tick.js:*:*)
1514
at process._tickCallback (internal/process/next_tick.js:*:*)
1615
42
1716
42
@@ -29,7 +28,7 @@ Error: hello
2928
at Socket.<anonymous> (bootstrap_node.js:*:*)
3029
at Socket.emit (events.js:*:*)
3130
at endReadableNT (_stream_readable.js:*:*)
32-
at _combinedTickCallback (internal/process/next_tick.js:*:*)
31+
at process._tickCallback (internal/process/next_tick.js:*:*)
3332
[stdin]:1
3433
throw new Error("hello")
3534
^
@@ -44,7 +43,7 @@ Error: hello
4443
at Socket.<anonymous> (bootstrap_node.js:*:*)
4544
at Socket.emit (events.js:*:*)
4645
at endReadableNT (_stream_readable.js:*:*)
47-
at _combinedTickCallback (internal/process/next_tick.js:*:*)
46+
at process._tickCallback (internal/process/next_tick.js:*:*)
4847
100
4948
[stdin]:1
5049
var x = 100; y = x;
@@ -60,7 +59,7 @@ ReferenceError: y is not defined
6059
at Socket.<anonymous> (bootstrap_node.js:*:*)
6160
at Socket.emit (events.js:*:*)
6261
at endReadableNT (_stream_readable.js:*:*)
63-
at _combinedTickCallback (internal/process/next_tick.js:*:*)
62+
at process._tickCallback (internal/process/next_tick.js:*:*)
6463

6564
[stdin]:1
6665
var ______________________________________________; throw 10
Collapse file

‎test/message/unhandled_promise_trace_warnings.out‎

Copy file name to clipboardExpand all lines: test/message/unhandled_promise_trace_warnings.out
-2Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
at *
1616
at *
1717
at *
18-
at *
1918
(node:*) Error: This was rejected
2019
at * (*test*message*unhandled_promise_trace_warnings.js:*)
2120
at *
@@ -34,7 +33,6 @@
3433
at *
3534
at *
3635
at *
37-
at *
3836
(node:*) PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 1)
3937
at getAsynchronousRejectionWarningObject (internal/process/promises.js:*)
4038
at rejectionHandled (internal/process/promises.js:*)

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.