-
Notifications
You must be signed in to change notification settings - Fork 29.8k
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
stream: improve Readable.read() performance #7077
Conversation
/cc @nodejs/streams |
should buffer list maybe live in the internals folder ? |
@calvinmetcalf Debatable but I left it there since it's only used by Readable and it's better if Readable isn't referencing anything from |
I can extract that other file easily, I'm more worried about exporting that from readable which is not on the api |
@calvinmetcalf I don't understand what you mean by "is not on the api." |
sorry, misspoke, I meant that I didn't like exporting that new thing from readable |
@calvinmetcalf I can remove it if necessary I suppose, but then we'd end up duplicating some of it in the tests I had to modify. I thought it would be better not to have to keep two separate "implementations" in sync. |
I was thinking that if that file got moved to something in internal, then you could just require that for the tests and require it for from stream_readable and don't worry about the readable-stream module, it won't be much of an inconvenience. |
e90c652
to
1ae67c9
Compare
@calvinmetcalf Ok, moved to internal. |
1ae67c9
to
47d6cc0
Compare
} | ||
|
||
BufferList.prototype.push = function(v) { | ||
const entry = { data: v, next: null }; |
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.
Do you think it could help to create an Entry
class to increase property access performance?
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.
I just tried it and it doesn't seem to make any real difference. If anything it seems to slow things down a little bit.
/cc @nodejs/collaborators Anyone have any comments/questions/LGTMs on this? |
else | ||
buf.copy(ret, c, 0, cpy); | ||
// result spans more than one buffer | ||
ret = (hasStrings |
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.
I'm not sure on the style guide on this, but the outer braces seem useless.
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.
You mean the parens? shrug I always add that when "assigning" a ternary statement to a variable as it seems more readable/clear to me.
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.
I noticed :) I don't really mind, just curious if there's any consensus on this. No blocker, no worries.
And sorry, yeah, parens (I, non-native English speaker, always get these mixed up... sigh)
f1922f1
to
1f2fbc2
Compare
|
||
var common = require('../common'); | ||
var v8 = require('v8'); | ||
var Readable = require('stream').Readable; |
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.
const
?
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.
Fixed.
1f2fbc2
to
729b645
Compare
First read through looks good but I'll have to go through in more detail tomorrow. In general tho, if @nodejs/streams is happy, then ++ |
Do we have a CITGM run? If that passes.. LGTM. just with one catch.. Let's give this a long time before we backport. |
the job was aborted, should we kick it off again? |
@mcollina It was aborted most likely because the ppcle machine is/was still down. The lodash failure on OSX1010 looks like an npm or citgm failure since it failed on installation of the package. Otherwise citgm is green. |
LGTM as semver-minor. |
read() performance is improved most by switching from an array to a linked list for storing buffered data. However, other changes that also contribute include: making some hot functions inlinable, faster read() argument checking, and misc code rearrangement to avoid unnecessary code execution. PR-URL: #7077 Reviewed-By: Calvin Metcalf <calvin.metcalf@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
read() performance is improved most by switching from an array to a linked list for storing buffered data. However, other changes that also contribute include: making some hot functions inlinable, faster read() argument checking, and misc code rearrangement to avoid unnecessary code execution. PR-URL: #7077 Reviewed-By: Calvin Metcalf <calvin.metcalf@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
@mcollina Why is this |
Notable changes: * buffer: Added `buffer.swap64()` to compliment `swap16()` & `swap32()`. (Zach Bjornson) #7157 * build: New `configure` options have been added for building Node.js as a shared library. (Stefan Budeanu) #6994 - The options are: `--shared`, `--without-v8-platform` & `--without-bundled-v8`. * crypto: Root certificates have been updated. (Ben Noordhuis) #7363 * debugger: The server address is now configurable via `--debug=<address>:<port>`. (Ben Noordhuis) #3316 * npm: Upgraded npm to v3.10.3 (Kat Marchán) #7515 & (Rebecca Turner) #7410 * readline: Added the `prompt` option to the readline constructor. (Evan Lucas) #7125 * repl / vm: `sigint`/`ctrl+c` will now break out of infinite loops without stopping the Node.js instance. (Anna Henningsen) #6635 * src: - Added a `node::FreeEnvironment` public C++ API. (Cheng Zhao) #3098 - Refactored `require('constants')`, constants are now available directly from their respective modules. (James M Snell) #6534 * stream: Improved `readable.read()` performance by up to 70%. (Brian White) #7077 * timers: `setImmediate()` is now up to 150% faster in some situations. (Andras) #6436 * util: Added a `breakLength` option to `util.inspect()` to control how objects are formatted across lines. (cjihrig) #7499 * v8-inspector: Experimental support has been added for debugging Node.js over the inspector protocol. (Ali Ijaz Sheikh) #6792 - *Note: This feature is experimental, and it could be altered or removed.* - You can try this feature by running Node.js with the `--inspect` flag. Refs: #7441 PR-URL: #7550
@Fishrock123 avoiding possible breakages in a patch release. IMHO performance optimizations are semver-minor, as performance is a backward-compatible feature. |
@mcollina So you are saying this is How this works is, in this order:
|
Notable changes: * buffer: Added `buffer.swap64()` to compliment `swap16()` & `swap32()`. (Zach Bjornson) #7157 * build: New `configure` options have been added for building Node.js as a shared library. (Stefan Budeanu) #6994 - The options are: `--shared`, `--without-v8-platform` & `--without-bundled-v8`. * crypto: Root certificates have been updated. (Ben Noordhuis) #7363 * debugger: The server address is now configurable via `--debug=<address>:<port>`. (Ben Noordhuis) #3316 * npm: Upgraded npm to v3.10.3 (Kat Marchán) #7515 & (Rebecca Turner) #7410 * readline: Added the `prompt` option to the readline constructor. (Evan Lucas) #7125 * repl / vm: `sigint`/`ctrl+c` will now break out of infinite loops without stopping the Node.js instance. (Anna Henningsen) #6635 * src: - Added a `node::FreeEnvironment` public C++ API. (Cheng Zhao) #3098 - Refactored `require('constants')`, constants are now available directly from their respective modules. (James M Snell) #6534 * stream: Improved `readable.read()` performance by up to 70%. (Brian White) #7077 * timers: `setImmediate()` is now up to 150% faster in some situations. (Andras) #6436 * util: Added a `breakLength` option to `util.inspect()` to control how objects are formatted across lines. (cjihrig) #7499 * v8-inspector: Experimental support has been added for debugging Node.js over the inspector protocol. (Ali Ijaz Sheikh) #6792 - *Note: This feature is experimental, and it could be altered or removed.* - You can try this feature by running Node.js with the `--inspect` flag. Refs: #7441 PR-URL: #7550
no and no. This is a performance optimization, e.g. a new feature for me. |
So... don't land on LTS is what I'm getting out of this. :) |
@Fishrock123 I think this one will be fine on LTS, but I would recommend porting it after some months, not weeks. Something like "land when the new LTS is out". |
Notable changes: * buffer: Added `buffer.swap64()` to compliment `swap16()` & `swap32()`. (Zach Bjornson) #7157 * build: New `configure` options have been added for building Node.js as a shared library. (Stefan Budeanu) #6994 - The options are: `--shared`, `--without-v8-platform` & `--without-bundled-v8`. * crypto: Root certificates have been updated. (Ben Noordhuis) #7363 * debugger: The server address is now configurable via `--debug=<address>:<port>`. (Ben Noordhuis) #3316 * npm: Upgraded npm to v3.10.3 (Kat Marchán) #7515 & (Rebecca Turner) #7410 * readline: Added the `prompt` option to the readline constructor. (Evan Lucas) #7125 * repl / vm: `sigint`/`ctrl+c` will now break out of infinite loops without stopping the Node.js instance. (Anna Henningsen) #6635 * src: - Added a `node::FreeEnvironment` public C++ API. (Cheng Zhao) #3098 - Refactored `require('constants')`, constants are now available directly from their respective modules. (James M Snell) #6534 * stream: Improved `readable.read()` performance by up to 70%. (Brian White) #7077 * timers: `setImmediate()` is now up to 150% faster in some situations. (Andras) #6436 * util: Added a `breakLength` option to `util.inspect()` to control how objects are formatted across lines. (cjihrig) #7499 * v8-inspector: Experimental support has been added for debugging Node.js over the inspector protocol. (Ali Ijaz Sheikh) #6792 - *Note: This feature is experimental, and it could be altered or removed.* - You can try this feature by running Node.js with the `--inspect` flag. Refs: #7441 PR-URL: #7550
### Notable changes * **buffer**: Added `buffer.swap64()` to compliment `swap16()` & `swap32()`. (Zach Bjornson) [#7157](nodejs/node#7157) * **build**: New `configure` options have been added for building Node.js as a shared library. (Stefan Budeanu) [#6994](nodejs/node#6994) - The options are: `--shared`, `--without-v8-platform` & `--without-bundled-v8`. * **crypto**: Root certificates have been updated. (Ben Noordhuis) [#7363](nodejs/node#7363) * **debugger**: The server address is now configurable via `--debug=<address>:<port>`. (Ben Noordhuis) [#3316](nodejs/node#3316) * **npm**: Upgraded npm to v3.10.3 (Kat Marchán) [#7515](nodejs/node#7515) & (Rebecca Turner) [#7410](nodejs/node#7410) * **readline**: Added the `prompt` option to the readline constructor. (Evan Lucas) [#7125](nodejs/node#7125) * **repl / vm**: `sigint`/`ctrl+c` will now break out of infinite loops without stopping the Node.js instance. (Anna Henningsen) [#6635](nodejs/node#6635) * **src**: - Added a `node::FreeEnvironment` public C++ API. (Cheng Zhao) [#3098](nodejs/node#3098) - Refactored `require('constants')`, constants are now available directly from their respective modules. (James M Snell) [#6534](nodejs/node#6534) * **stream**: Improved `readable.read()` performance by up to 70%. (Brian White) [#7077](nodejs/node#7077) * **timers**: `setImmediate()` is now up to 150% faster in some situations. (Andras) [#6436](nodejs/node#6436) * **util**: Added a `breakLength` option to `util.inspect()` to control how objects are formatted across lines. (cjihrig) [#7499](nodejs/node#7499) * **v8-inspector**: Experimental support has been added for debugging Node.js over the inspector protocol. (Ali Ijaz Sheikh) [#6792](nodejs/node#6792) - **Note: This feature is _experimental_, and it could be altered or removed.** - You can try this feature by running Node.js with the `--inspect` flag.
@Fishrock123 @mcollina just re your above conversation, this ended up breaking duplexify (https://www.npmjs.com/package/duplexify) because it expected the _buffer to be an array |
I feared something like that would have happened. I think we should make a final decision either to semver I'm happy we got this early (before a backport to readable-stream). |
They're clearly private. If people want to manipulate them, we can expose public API for that. The duplexify package authors could've pushed/asked for that, and still can imho. |
@mcollina could you open a separate issue for the semver discussion so we don't take over this one? for the record i think reading some of the properties in _readableState is essential for a bunch of use-cases. like figuring out if a stream is in objectMode, figuring out if it ended but still has data in its read buffer etc. |
@mafintosh done ^ |
Checklist
Affected core subsystem(s)
Description of change
read()
performance is improved most by switching from an array to a linked list for storing buffered data. However, other changes that also contribute include: making some hot functions inlinable, fasterread()
argument checking, and misc code rearrangement to avoid unnecessary code execution.These improvements only exist for when
n
is supplied toread()
, otherwise performance is the same.Note: I did change how negative
n
values are interpreted when in object mode. Before this PR, negativen
values were interpreted as 1 inhowMuchToRead()
. I changed this to instead return 0 to match how negativen
values are interpreted for non-object mode streams.Results from the included benchmarks: