-
Notifications
You must be signed in to change notification settings - Fork 30.5k
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
fs: speed up fs.WriteStream#_write #2944
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1840,30 +1840,45 @@ fs.FileWriteStream = fs.WriteStream; // support the legacy name | |
|
||
|
||
WriteStream.prototype.open = function() { | ||
const self = this; | ||
|
||
fs.open(this.path, this.flags, this.mode, function(er, fd) { | ||
if (er) { | ||
this.destroy(); | ||
this.emit('error', er); | ||
self.destroy(); | ||
self.emit('error', er); | ||
return; | ||
} | ||
|
||
this.fd = fd; | ||
this.emit('open', fd); | ||
}.bind(this)); | ||
self.fd = fd; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems like a good place to put an arrow function. I'm curious about the perf vs this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Afaik There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was wary about them as well, but after a bunch of testing found that they're just as fast as normal functions in the same situation. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Though, |
||
self.emit('open', fd); | ||
}); | ||
}; | ||
|
||
|
||
function write(fd, buffer, position, callback) { | ||
function wrapper(err, written) { | ||
// Retain a reference to buffer so that it can't be GC'ed too soon. | ||
callback(err, written || 0, buffer); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @trevnorris Any news on the solution to these wrappers? If we could avoid a closure for each of these write calls everywhere, I think that would improve performance (or lower memory usage) a bit more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You won't see much if any gain in terms of performance. The change is more for code cleanliness. Will have to make the change of passing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't know what the plan is, but are you saying we would still need a wrapper? Perhaps you can elaborate a bit on what this is really all about? :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Once the buffer has left JS scope then GC will clean it up. Even though it's still being used. One alternative is that the buffer bubbles through the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Understood, thanks. |
||
|
||
var req = new FSReqWrap(); | ||
req.oncomplete = wrapper; | ||
binding.writeBuffer(fd, buffer, 0, buffer.length, position, req); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This line is what this PR is all about: avoiding all the stuff in fs.write that we already know does not apply to this use-case. |
||
} | ||
|
||
|
||
WriteStream.prototype._write = function(data, encoding, cb) { | ||
if (!(data instanceof Buffer)) | ||
return this.emit('error', new Error('Invalid data')); | ||
return this.emit('error', new TypeError('Invalid data')); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm pretty sure this isn't necessary anyways, as Writable guarantees data will be a Buffer. Perhaps, if the C++ throws on not-a-buffer, this could be removed entirely? (As to throw on evil There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, I think you are right! And C++ does check for this luckily. |
||
|
||
if (typeof this.fd !== 'number') | ||
return this.once('open', function() { | ||
this._write(data, encoding, cb); | ||
}); | ||
|
||
var self = this; | ||
fs.write(this.fd, data, 0, data.length, this.pos, function(er, bytes) { | ||
|
||
write(this.fd, data, this.pos, function(er, bytes) { | ||
if (er) { | ||
self.destroy(); | ||
return cb(er); | ||
|
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.
latest node supports arrow functions so why not use them?
Ref: http://jsperf.com/arrow-functions-vs-bind
Ref: http://jsperf.com/arrow-vs-bind
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 don't think that's my call to make. I would like to see the Node core members formally embrace it before throwing my warm and fuzzy ES6 feelings into each PR.
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.
Don't know about "embracing" it, but we're not going to enforce it. It's a stylistic call to save a few chars in a scenario like this.
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.
Just so we're clear on future PRs, are arrow functions permitted in core now? I know they're supported by V8, but is there any reason NOT to use them?
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.
They're permitted. Performance is on par w/ normal functions. Only place I'd suggest they be used is if
this
needs to propagate. Other than that it's nothing more than a style thing.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.
According to my benchmark, arrow functions actually seem to be reliably faster than regular functions.
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.
@brendanashworth Try reordering the runs. ;)
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.
sigh, v8 is confusing sometimes.