Skip to content

lib,src: improve writev() performance for Buffers - #13187

Merged
mscdex merged 1 commit into
nodejs:masterfrom
mscdex:net-writev-perf
May 26, 2017
Merged

lib,src: improve writev() performance for Buffers#13187
mscdex merged 1 commit into
nodejs:masterfrom
mscdex:net-writev-perf

Conversation

@mscdex

@mscdexmscdex commented May 24, 2017

Copy link
Copy Markdown
Contributor

It's pretty common to write only Buffers to a socket, so we can optimize for that case in a couple of ways whenever we know we have all Buffers queued up for writev():

  • Reuse the existing array of chunks
  • Try to write the Buffers (or at least as much as possible) immediately without having to create a WriteWrap instance first. This optimization is one that is already being done when write()ing a single Buffer (or a single string for that matter) to a socket.

Benchmark results:

 improvement confidence p.value
net/net-c2s-cork.js dur=5 type="buf" len=1024 32.36 % *** 3.042522e-23
net/net-c2s-cork.js dur=5 type="buf" len=128 27.74 % *** 5.759989e-59
net/net-c2s-cork.js dur=5 type="buf" len=16 30.72 % *** 1.594866e-57
net/net-c2s-cork.js dur=5 type="buf" len=32 31.18 % *** 8.568983e-62
net/net-c2s-cork.js dur=5 type="buf" len=4 24.99 % *** 2.220787e-64
net/net-c2s-cork.js dur=5 type="buf" len=512 29.04 % *** 3.058048e-32
net/net-c2s-cork.js dur=5 type="buf" len=64 29.34 % *** 5.167685e-50
net/net-c2s-cork.js dur=5 type="buf" len=8 11.35 % *** 4.258937e-43

CI: https://ci.nodejs.org/job/node-test-pull-request/8271/
CI for FIPS (since it failed initially): https://ci.nodejs.org/job/node-test-commit-linux-fips/8624/

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • commit message follows commit guidelines
Affected core subsystem(s)
  • net
  • stream

@mscdexmscdex added c++ Issues and PRs that require attention from people who are familiar with C++. net Issues and PRs related to the net subsystem. performance Issues and PRs related to the performance of Node.js. stream Issues and PRs related to the stream subsystem. labels May 24, 2017
@nodejs-github-botnodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. net Issues and PRs related to the net subsystem. stream Issues and PRs related to the stream subsystem. labels May 24, 2017
Comment threadlib/_stream_writable.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.

I'd probably do allBuffers = allBuffers && entry.isBuf

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 tried something similar (continuing the rest of the loop without any conditional) and did not see any difference in performance.

Comment threadsrc/stream_base.cc 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.

Can you use the overload that returns a Maybe<bool>, or alternatively use IsTrue() instead?

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.

Changed.

Comment threadsrc/stream_base.cc 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.

nit: I’d really just write / 2, it’s clearer and the resulting code will be the same

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.

That's copied from before these changes. It's also similar to what was already being used in js.

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.

Yeah, but in JS that has a different meaning. ¯\_(ツ)_/¯ If you want to keep it it’s fine.

Comment threadsrc/stream_base.cc 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.

Heads up, this is going to conflict with #13174 which removes the comment (because GetAsyncWrap() does actually never return a null pointer), so feel free to remove it here as well

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'll just wait until that lands first and I'll rebase.

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.

@mscdex Landed, you can rebase now

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.

Done.

Comment threadsrc/stream_base.cc 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.

nit: chunk->IsUint8Array()

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.

This was also copied from before these changes. I think changing it to check for a more general type is outside the scope of this PR.

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.

I think changing it to check for a more general type is outside the scope of this PR.

It’s literally the same thing, just inlined. :)

@mscdexmscdexMay 24, 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.

Actually HasInstance() in master and v8.x use IsArrayBufferView() while v7.x and v6.x use IsUint8Array(). Ideally this could be backported more easily if we kept HasInstance()?

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.

Oh, right, we made that switch. Idc, you can also keep Buffer::HasInstance.

@mscdex
mscdexforce-pushed the net-writev-perf branch 2 times, most recently from c5814a0 to fd84f30CompareMay 25, 2017 18:33
PR-URL: nodejs#13187
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
@mscdex
mscdex merged commit 01a1022 into nodejs:masterMay 26, 2017
@mscdex
mscdex deleted the net-writev-perf branch May 26, 2017 08:33
jasnell pushed a commit that referenced this pull request May 28, 2017
PR-URL: #13187
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
@jasnelljasnell mentioned this pull request May 28, 2017
@gibfahngibfahn mentioned this pull request Jun 15, 2017
3 tasks
@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 we consider this for LTS? if so it needs to bake for a bit. Please change labels as appropriate

@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

c++Issues and PRs that require attention from people who are familiar with C++.netIssues and PRs related to the net subsystem.performanceIssues and PRs related to the performance of Node.js.streamIssues and PRs related to the stream subsystem.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@mscdex@MylesBorins@addaleax@benjamingr@nodejs-github-bot