-
Notifications
You must be signed in to change notification settings - Fork 29.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Optimize child_process IPC for large data #10557
Conversation
d648a5b
to
f99d46f
Compare
f99d46f
to
4b13964
Compare
//Linebreak is used as a message end sign | ||
while ((i = jsonBuffer.indexOf('\n', start)) >= 0) { | ||
var json = jsonBuffer.slice(start, i); | ||
chunks.forEach(function(json) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
forEach()
is slower than a normal for
loop.
4bfbcbc
to
01da0d4
Compare
forEach() removed! setTimeout() is 20: setTimeout() is 0: |
01da0d4
to
ccac4b4
Compare
I wonder how it performs with setImmediate or possibly other ways of queueing up callbacks |
I don't think the |
58f6cc0 fixes New benchmark result with setImmediate():
|
@@ -498,9 +498,9 @@ function setupChannel(target, channel) { | |||
var queue = target._handleQueue; | |||
target._handleQueue = null; | |||
|
|||
queue.forEach(function(args) { | |||
for (var args in queue) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this work? for (var … in …)
iterates over the indices of the array, so it does not do the same thing as for (var i = 0; i < args.length; ++i)
Oops... test was failing. Fixed in de82d97..! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes in lib
LGTM, can’t really speak up for the benchmark part
Squashed from: - child_process: fix IPC bench to obey send() ret val - child_process: fix IPC benchmark message has two more bytes - child_process: use setImmediate for IPC bench PR-URL: nodejs#10557 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Anna Henningsen <anna@addaleax.net>
Squashed from: - child_process: stop indexOf() on whole IPC buffer - child_process: get rid of forEach() and slice() in IPC - child_process: get rid of another forEach() in IPC Fixes: nodejs#3145 PR-URL: nodejs#10557 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Anna Henningsen <anna@addaleax.net>
Squashed from: - child_process: fix IPC bench to obey send() ret val - child_process: fix IPC benchmark message has two more bytes - child_process: use setImmediate for IPC bench PR-URL: nodejs#10557 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Anna Henningsen <anna@addaleax.net>
Squashed from: - child_process: stop indexOf() on whole IPC buffer - child_process: get rid of forEach() and slice() in IPC - child_process: get rid of another forEach() in IPC Fixes: nodejs#3145 PR-URL: nodejs#10557 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Anna Henningsen <anna@addaleax.net>
Squashed from: - child_process: fix IPC bench to obey send() ret val - child_process: fix IPC benchmark message has two more bytes - child_process: use setImmediate for IPC bench PR-URL: nodejs#10557 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Anna Henningsen <anna@addaleax.net>
Squashed from: - child_process: stop indexOf() on whole IPC buffer - child_process: get rid of forEach() and slice() in IPC - child_process: get rid of another forEach() in IPC Fixes: nodejs#3145 PR-URL: nodejs#10557 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Anna Henningsen <anna@addaleax.net>
Squashed from: - child_process: fix IPC bench to obey send() ret val - child_process: fix IPC benchmark message has two more bytes - child_process: use setImmediate for IPC bench PR-URL: nodejs#10557 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Anna Henningsen <anna@addaleax.net>
Squashed from: - child_process: stop indexOf() on whole IPC buffer - child_process: get rid of forEach() and slice() in IPC - child_process: get rid of another forEach() in IPC Fixes: nodejs#3145 PR-URL: nodejs#10557 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Anna Henningsen <anna@addaleax.net>
Is this something we will want to backport? Should it bake a bit longer first? |
ping |
Squashed from: - child_process: fix IPC bench to obey send() ret val - child_process: fix IPC benchmark message has two more bytes - child_process: use setImmediate for IPC bench PR-URL: #10557 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Anna Henningsen <anna@addaleax.net>
Squashed from: - child_process: stop indexOf() on whole IPC buffer - child_process: get rid of forEach() and slice() in IPC - child_process: get rid of another forEach() in IPC Fixes: #3145 PR-URL: #10557 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Anna Henningsen <anna@addaleax.net>
@MylesBorins This should be fine to backport to v6.x… I’ve cherry-picked the changes here to |
Squashed from: - child_process: fix IPC bench to obey send() ret val - child_process: fix IPC benchmark message has two more bytes - child_process: use setImmediate for IPC bench PR-URL: nodejs/node#10557 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Anna Henningsen <anna@addaleax.net>
Squashed from: - child_process: stop indexOf() on whole IPC buffer - child_process: get rid of forEach() and slice() in IPC - child_process: get rid of another forEach() in IPC Fixes: nodejs/node#3145 PR-URL: nodejs/node#10557 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Anna Henningsen <anna@addaleax.net>
jsonBuffer.indexOf('\n', start)
inchannel.onread
(internal/child_process.js
) dramatically slows down whenjsonBuffer
is very large.jsonBuffer
does not contains linebreak beforejsonBuffer += decoder.write(pool)
call, so checking linebreaks in return value ofdecoder.write(pool)
is enough to parse chunks.This increases total bytes received in 5 secs by 2-4x in benchmark...!
I found this when developing vscode plugin which returns very large result (around 10MB):
rubyide/vscode-ruby#107
Also vscode core has workaround for this bottleneck:
microsoft/vscode#6026 (comment)
Also fixed benchmark script which only shows zero.
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passesAffected core subsystem(s)
child_process
Benchmark result
Mac OS X 10.12.2
MacBook Pro (Retina, 15-inch, Mid 2014)
2.2 GHz Intel Core i7
Before:
child_process/child-process-read-ipc.js dur=5 len=64: 7,583,464
child_process/child-process-read-ipc.js dur=5 len=256: 10,687,553
child_process/child-process-read-ipc.js dur=5 len=1024: 6,279,313
child_process/child-process-read-ipc.js dur=5 len=4096: 6,319,896
child_process/child-process-read-ipc.js dur=5 len=16384: 6,482,388
child_process/child-process-read-ipc.js dur=5 len=65536: 8,580,203
child_process/child-process-read-ipc.js dur=5 len=1048576: 13,398,807
child_process/child-process-read-ipc.js dur=5 len=16777216: 0
After:
child_process/child-process-read-ipc.js dur=5 len=64: 9,131,734
child_process/child-process-read-ipc.js dur=5 len=256: 10,502,876
child_process/child-process-read-ipc.js dur=5 len=1024: 6,272,325
child_process/child-process-read-ipc.js dur=5 len=4096: 6,195,482
child_process/child-process-read-ipc.js dur=5 len=16384: 6,505,698
child_process/child-process-read-ipc.js dur=5 len=65536: 8,513,730
child_process/child-process-read-ipc.js dur=5 len=1048576: 40,615,305
child_process/child-process-read-ipc.js dur=5 len=16777216: 30,183,113
When setTimeout() in benchmark is 0:
(I have no idea why this produces quite different result.)
Before:
child_process/child-process-read-ipc.js dur=5 len=64: 11,924,365
child_process/child-process-read-ipc.js dur=5 len=256: 34,004,413
child_process/child-process-read-ipc.js dur=5 len=1024: 51,082,451
child_process/child-process-read-ipc.js dur=5 len=4096: 61,968,471
child_process/child-process-read-ipc.js dur=5 len=16384: 59,297,771
child_process/child-process-read-ipc.js dur=5 len=65536: 59,533,374
child_process/child-process-read-ipc.js dur=5 len=1048576: 6,704,920
child_process/child-process-read-ipc.js dur=5 len=16777216: 0
After:
child_process/child-process-read-ipc.js dur=5 len=64: 12,209,873
child_process/child-process-read-ipc.js dur=5 len=256: 36,964,340
child_process/child-process-read-ipc.js dur=5 len=1024: 50,775,987
child_process/child-process-read-ipc.js dur=5 len=4096: 79,817,420
child_process/child-process-read-ipc.js dur=5 len=16384: 92,115,253
child_process/child-process-read-ipc.js dur=5 len=65536: 105,704,985
child_process/child-process-read-ipc.js dur=5 len=1048576: 23,256,095
child_process/child-process-read-ipc.js dur=5 len=16777216: 0