fs: include more fs.stat*() optimizations#11665
fs: include more fs.stat*() optimizations#11665mscdex wants to merge 2 commits intonodejs:masterfrom
Conversation
|
For what it's worth, this will break some modules like mock-fs which rely on mutating I acknowledge that |
|
@not-an-aardvark Well, in a recent PR I was told not to worry about |
|
Fair enough. The reason I bring this up is that #11522 ended up causing tschaub/mock-fs#197 and breaking some builds. (I'm not trying to argue that this particular decision was justified/unjustified -- I just want to make sure that these decisions are made with full information on what they might break downstream.) |
lib/fs.js
Outdated
There was a problem hiding this comment.
Missing dot. Happens in quite a few other places. I won't point them out but please fix them up.
lib/fs.js
Outdated
lib/fs.js
Outdated
There was a problem hiding this comment.
You could move this to after the if statement if you make it compare on the statValues entry directly.
lib/fs.js
Outdated
There was a problem hiding this comment.
Some field index constants would be good to have. Using number literals obscures it too much.
src/node_stat_watcher.cc
Outdated
There was a problem hiding this comment.
You can simplify this now to:
Local<Value> arg = Integer::New(env->isolate(), status);
wrap->MakeCallback(env->onchange_string(), 1, &arg);
lib/fs.js
Outdated
There was a problem hiding this comment.
You can drop the constants. now here.
lib/fs.js
Outdated
lib/fs.js
Outdated
src/node_file.cc
Outdated
lib/fs.js
Outdated
There was a problem hiding this comment.
btw, it's worth noting that I had tried to convert this to a ES6 Class just to see what would happen and it yielded a 50% perf reduction.
jasnell
left a comment
There was a problem hiding this comment.
LGTM once @bnoordhuis' comments are addressed
69c14fc to
1fa23da
Compare
lib/fs.js
Outdated
There was a problem hiding this comment.
It might be good to leave a comment to indicate that these values refer to .nlink
There was a problem hiding this comment.
In another comment I suggested adding constants for the field indices, that would help with legibility.
There was a problem hiding this comment.
Changed here as well now. I misunderstood the original suggestion for this line.
lib/fs.js
Outdated
There was a problem hiding this comment.
In another comment I suggested adding constants for the field indices, that would help with legibility.
e072aa3 to
add40be
Compare
|
CI again after making suggested changes: https://ci.nodejs.org/job/node-test-pull-request/6719/ |
|
What I had in mind was more along the lines of |
|
@bnoordhuis I was trying to avoid lookups where possible as I'm not sure V8 will always inline the value, even if |
|
Valid concern. One more argument for reintroducing macros, I suppose. Alternatively, you could write them as |
We should warn them ahead of time still I think. @mscdex do you figure the new way is still shimmable? |
|
@Fishrock123 Support for the |
add40be to
721a107
Compare
|
Rebased and added inline comments next to the Float64Array's indices. Any further comments/questions/suggestions @nodejs/collaborators? |
Including: * Move async *stat() functions to FillStatsArray() now used by the sync *stat() functions * Avoid creating fs.Stats instances for implicit async/sync *stat() calls used in various fs functions * Store reference to Float64Array data on C++ side for easier/faster access, instead of passing from JS to C++ on every async/sync *stat() call PR-URL: #11665 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Including: * Skip URL instance check for common (string) cases * Avoid regexp on non-Windows platforms when parsing the root of a path * Skip call to `getOptions()` in common case where no `options` is passed * Avoid `hasOwnProperty()` PR-URL: #11665 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
|
Landed in 6a5ab5d...7109774 |
Including: * Move async *stat() functions to FillStatsArray() now used by the sync *stat() functions * Avoid creating fs.Stats instances for implicit async/sync *stat() calls used in various fs functions * Store reference to Float64Array data on C++ side for easier/faster access, instead of passing from JS to C++ on every async/sync *stat() call PR-URL: nodejs#11665 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Including: * Skip URL instance check for common (string) cases * Avoid regexp on non-Windows platforms when parsing the root of a path * Skip call to `getOptions()` in common case where no `options` is passed * Avoid `hasOwnProperty()` PR-URL: nodejs#11665 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
| fields = new double[2 * 14]; | ||
| env->set_fs_stats_field_array(fields); | ||
| } | ||
| Local<ArrayBuffer> ab = ArrayBuffer::New(env->isolate(), |
There was a problem hiding this comment.
@mscdex , Correct me if i am wrong, but ArrayBuffer::New() creates a buffer by default in externalizeMode. Who frees fields array in that case? May be you want to pass ArrayBufferCreationMode::kExternalized to this API?
There was a problem hiding this comment.
That is the default mode already? fields should never be freed by V8 according to the description, which is what we want.
There was a problem hiding this comment.
Right, but then how/when do we delete fields?
There was a problem hiding this comment.
May be you want to pass ArrayBufferCreationMode::kExternalized to this API?
What i meant was to pass ArrayBufferCreationMode::kInternalized instead.
There was a problem hiding this comment.
We don't. It's created once and stays for the life of the process, for whenever someone calls the fs.stat*() functions implicitly or explicitly.
|
@nodejs/ctc How do you feel about the semver-major-ness of these changes? Do you think it is warranted? The reason I ask is that apparently in some situations certain So either we could decide this PR really isn't semver-major and backport it as-is to v7.x which still has async Thoughts? |
|
@addaleax Ah ok I did not know it made it into v6.x. |
|
If there have been no regressions I'm good with downgrading thing to semver-minor and backporting. |
|
@jasnell Have enough people tested with master though since this was landed? |
|
Unsure. Preferably it would sit through at least one release on current before backporting. |
|
I think we'd need to make a decision sooner than that because of the issue I linked to. |
|
Doh, actually nevermind lol. For some reason I was reading that as backporting to v6. I'm good with backporting to v7. |
|
Well it's the same situation for v6 really, unless we want to decide differently for that branch. |
|
Yep, understood. Let's get it into a v7 release. Give it a week or two, then decide for v6. |
Including: * Move async *stat() functions to FillStatsArray() now used by the sync *stat() functions * Avoid creating fs.Stats instances for implicit async/sync *stat() calls used in various fs functions * Store reference to Float64Array data on C++ side for easier/faster access, instead of passing from JS to C++ on every async/sync *stat() call Backport-PR-URL: nodejs#11665 Fixes: nodejs#16496
Including: * Avoid regexp on non-Windows platforms when parsing the root of a path Backport-PR-URL: nodejs#11665
stat*()optimizations including:Move async
*stat()functions toFillStatsArray()now used by the sync*stat()functionsAvoid creating
fs.Statsinstances for implicit async/sync*stat()calls used in variousfsfunctionsStore reference to
Float64Arraydata on C++ side for easier/faster access, instead of passing from JS to C++ on every async/sync*stat()callAdditionally, there are some further
realpath*()optimizations, including:Skip URL instance check for common (string) cases
Avoid regexp on non-Windows platforms when parsing the root of a path
Skip call to
getOptions()in common case where nooptionsis passedAvoid
hasOwnProperty()Some benchmark results with all of the changes in this PR:
I'm initially marking this as semver-major because of the changes in
fs.readFile(),fs.readFileSync(), etc. in how they retrieve stats for files/directories. If someone monkey patchesfs.*sync*(), those monkey matched methods would no longer be called from those changed functions (fs.readFile(), etc.). If we feel we shouldn't be worried about this, then I will gladly remove the label.CI: https://ci.nodejs.org/job/node-test-pull-request/6674/
Checklist
make -j4 test(UNIX), orvcbuild test(Windows) passesAffected core subsystem(s)