Skip to content

child_process: improve ipc performance - #13459

Merged
mscdex merged 2 commits into
nodejs:masterfrom
mscdex:child_process-ipc-perf
Jun 9, 2017
Merged

child_process: improve ipc performance#13459
mscdex merged 2 commits into
nodejs:masterfrom
mscdex:child_process-ipc-perf

Conversation

@mscdex

@mscdexmscdex commented Jun 5, 2017

Copy link
Copy Markdown
Contributor

These commits reduce/improve nextTick() usage in the child_process IPC implementation.

I should point out that I wasn't sure if we should ever need nextTick() when receiving/emitting messages, so for now I just made sure that both all internal messages and only the first non-internal message in a group are emitted within the same tick.

There is a substantial performance improvement when removing nextTick() altogether for emitted messages. My thought was that these messages should always happen on at least the next tick anyway, so perhaps it would be safe to remove it completely? All tests pass with nextTick() completely removed from handleMessage().

Results with the current changes with the included benchmark:

 improvement confidence p.value
cluster/echo.js n=100000 sendsPerBroadcast=1 payload="object" workers=1 15.62 % *** 1.440552e-08
cluster/echo.js n=100000 sendsPerBroadcast=1 payload="string" workers=1 18.59 % *** 3.478095e-10
cluster/echo.js n=100000 sendsPerBroadcast=10 payload="object" workers=1 25.71 % *** 6.436977e-26
cluster/echo.js n=100000 sendsPerBroadcast=10 payload="string" workers=1 33.88 % *** 1.812799e-22

CI: https://ci.nodejs.org/job/node-test-pull-request/8473/

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • commit message follows commit guidelines
Affected core subsystem(s)
  • child_process

@mscdexmscdex added child_process Issues and PRs related to the child_process subsystem. performance Issues and PRs related to the performance of Node.js. labels Jun 5, 2017
@nodejs-github-botnodejs-github-bot added the child_process Issues and PRs related to the child_process subsystem. label Jun 5, 2017
@mscdex
mscdexforce-pushed the child_process-ipc-perf branch from 8dfec59 to a1bd681CompareJune 5, 2017 00:27
Comment threadlib/internal/child_process.js Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shave off a few more millis with const INTERNALPREFIX_LENGTH = INTERNAL_PREFIX.length

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, I know it can be simplified and probably optimized, but I opted to leave it as-is for now.

Comment threadlib/internal/child_process.js Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[question] since internal messages are rare, will adding a Object.hasOwnProperty(message, 'cmd') && fail faster than typeof message.cmd === 'string'?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this could be simplified but I opted to leave it as-is for now.

Comment threadlib/internal/child_process.js Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not check for isInternal on the raw chunk?

@mscdexmscdexJun 5, 2017

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It has to be parsed first. chunks here is just an array of (complete) JSON strings.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant implement a string based check. Can't we assume "innerMessages" will have a {cmd: NODE_ prefix? or at least include a , cmd: NODE_ substring? Might also be able to distinguish between three cases: user/inner/inner_with_handle, and turn the following compound if into a switch

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather not make assumptions about JSON.stringify() output.

Comment threadlib/internal/child_process.js Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

even if we don't do a string based check, returning 0,1,2 (for user / inner / NODE_HANDLE) will enable using a switch in L466

@mscdexmscdexJun 5, 2017

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's unlikely it'll matter much, I'll let someone else work on it if they want. My main focus on this PR is nextTick() usage.

@refack

Copy link
Copy Markdown
Contributor

@mscdex Thanks for the answers 🎩

@mscdex

Copy link
Copy Markdown
ContributorAuthor

Results with V8 5.9 now in master:

 improvement confidence p.value
cluster/echo.js n=100000 sendsPerBroadcast=1 payload="object" workers=1 11.22 % *** 4.196927e-10
cluster/echo.js n=100000 sendsPerBroadcast=1 payload="string" workers=1 14.63 % *** 4.344752e-10
cluster/echo.js n=100000 sendsPerBroadcast=10 payload="object" workers=1 17.93 % *** 1.171912e-15
cluster/echo.js n=100000 sendsPerBroadcast=10 payload="string" workers=1 26.25 % *** 6.978421e-19

@bnoordhuisbnoordhuis left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice optimization, LGTM.

Comment threadbenchmark/cluster/echo.js Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing wrong with this but you could ES6-ify it with for (const worker of Object.values(cluster.workers)). Whatever your preference.

I suppose it could even be a little faster because Object.values() doesn't walk the prototype chain but that's probably only a marginal benefit (and I didn't test so my intuition might very well be wrong.)

@mscdexmscdexJun 8, 2017

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW I literally copied it from the cluster docs. I know we were trying to be more on the conservative side when it comes to introducing ES* features to benchmarks because of possible incompatibilities with older branches. For example, Object.values() does not exist in node v4.x or v6.x (although it's apparently behind a flag in recent v6.x releases).

mscdex added 2 commits June 9, 2017 01:38
PR-URL: nodejs#13459
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
PR-URL: nodejs#13459
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
@mscdex
mscdexforce-pushed the child_process-ipc-perf branch from a1bd681 to 8208fdaCompareJune 9, 2017 05:39
@mscdex
mscdex merged commit 8208fda into nodejs:masterJun 9, 2017
@mscdex
mscdex deleted the child_process-ipc-perf branch June 9, 2017 05:41
addaleax pushed a commit that referenced this pull request Jun 10, 2017
PR-URL: #13459
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
addaleax pushed a commit that referenced this pull request Jun 10, 2017
PR-URL: #13459
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
@addaleaxaddaleax mentioned this pull request Jun 10, 2017
@gibfahngibfahn mentioned this pull request Jun 15, 2017
3 tasks
cjihrig added a commit to cjihrig/node that referenced this pull request Jun 24, 2017
This commit fixes a regression related to IPC 'message'
events. When messages are not emitted in the next tick,
a 'message' handler that throws can break the IPC read
loop.
Refs: nodejs#6909
Refs: nodejs#13459
Refs: nodejs#13648
PR-URL: nodejs#13856
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
addaleax pushed a commit that referenced this pull request Jun 29, 2017
This commit fixes a regression related to IPC 'message'
events. When messages are not emitted in the next tick,
a 'message' handler that throws can break the IPC read
loop.
Refs: #6909
Refs: #13459
Refs: #13648
PR-URL: #13856
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
addaleax pushed a commit that referenced this pull request Jul 11, 2017
This commit fixes a regression related to IPC 'message'
events. When messages are not emitted in the next tick,
a 'message' handler that throws can break the IPC read
loop.
Refs: #6909
Refs: #13459
Refs: #13648
PR-URL: #13856
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
@MylesBorinsMylesBorins added baking-for-lts PRs that need to wait before landing in a LTS release. lts-watch-v6.x labels Jul 17, 2017
@MylesBorins

Copy link
Copy Markdown
Contributor

should this land in LTS? If so it will need to bake a bit longer.

Please change labels as appropriate

addaleax pushed a commit that referenced this pull request Jul 18, 2017
This commit fixes a regression related to IPC 'message'
events. When messages are not emitted in the next tick,
a 'message' handler that throws can break the IPC read
loop.
Refs: #6909
Refs: #13459
Refs: #13648
PR-URL: #13856
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
@MylesBorinsMylesBorins removed the baking-for-lts PRs that need to wait before landing in a LTS release. label Aug 17, 2018
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

child_processIssues and PRs related to the child_process subsystem.performanceIssues and PRs related to the performance of Node.js.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@mscdex@refack@MylesBorins@bnoordhuis@nodejs-github-bot