-
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
fs: move getValidMode to c++ for better performance #49970
Conversation
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.
🚀 Amazing work!
fs/sync.js is merged into fs.js file. Additionally, commit queue doesn't work with github merge commits. Can you manually squash your commits into 1? |
da7728f
to
cd54612
Compare
Rebased and squashed 😄 |
c3db742
to
5a5e3f6
Compare
Build fails for macOS |
It seems that the macros F_Ok, W_OK, R_OK and X_OK aren't defined in macOS. Maybe I can add an |
Try this: // F_OK etc. constants
#ifdef _WIN32
#include "uv.h"
#else
#include <unistd.h>
#endif edit: |
8eb3d60
to
a8ec116
Compare
Still needs unistd.h on macos. |
1b6b918
to
7074cd9
Compare
7074cd9
to
6cce9a8
Compare
6cce9a8
to
13d81ac
Compare
@tniessen The goal is to remove JS implementation of fs operations to open up room for V8 fast api (by removing functions that eventually unflattens the string). I personally think this is the correct path since error paths on filesystem is pretty common (although I can't back this claim with a scientific proof at this time) |
While that might be true for some cases, passing an invalid
That's a reasonable goal, I suppose, but the commit message sounds as if this change itself is motivated by an immediate performance improvement. That's all I was pointing out :) More importantly, this is a breaking change. |
Yeah, the commit message can be improved. I missed the part where why this is a breaking change. @tniessen |
Unless I'm missing something, some functions now don't throw synchronously anymore but instead report the validation error to the callback, which seems unusual for argument validation. I am not sure if that's desirable (or if we treat these things as semver-major). |
); | ||
const src = './test/fixtures/copy/kitchen-sink'; | ||
const dest = nextdir(); | ||
cp(src, dest, mustNotMutateObjectDeep({ recursive: true, mode: -1 }), (err) => { |
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.
The callback must be wrapped in mustCall()
. But I am really not sure if argument validation errors should be async, it seems very unusual.
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.
Hmm...the THROW_
macros being run before the AsyncDestCall
means this should actually be thrown synchronously, so it wouldn't get to the callback at all. Seems to me like it should be throwing from the cp(...)
call itself though, so I'm not sure how it could be getting to the rest of the test if that's the case. 🤔
Yes, is there any way to keep it synchronous while calling the validation function on the c++ land? |
Wouldn't the use of the I'm not seeing how any of these errors could become async from this. 🤔 |
Premature approval. Looks like the tests need some work. 🤔
I made some investigation and it turns out that Lines 259 to 265 in 6b599a3
So when the copyFile binding is called, it's already running asynchronously or am I missing something? I don't know how could we handle this case. One option is to keep the validation of |
await assert.rejects( | ||
fs.promises.cp('a', 'b', { | ||
fs.promises.cp(src, dest, mustNotMutateObjectDeep({ | ||
recursive: true, |
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.
Why recursive is needed now?
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.
Without it, the test throws ERR_FS_EISDIR
instead of ERR_OUT_OF_RANGE
.
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.
So this is a breaking change, right?
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.
Thinking about it now, I think so because if someone was checking for an mode
error in fs.cp
synchronously, this behavior would change to async. We could keep using getValidMode
on the JS side just for fs.cp
which is the only problematic function or don't make these changes at all. Or maybe there is another way, idk.
I flagged it as |
Eventually we'll move everything to C++ side to enable using V8 APIs. IMHO, This is a step in the correct direction. |
IMHO making parameter validation async is not. Performance improvements generally should not result in breaking changes, unless the design (and not just the implementation) changes. |
Yeah, input validation should always remain sync. I think situations like this where one function delegates to others internally we should have an internal implementation without the validation that can be shared so we can raise all validation to before it runs any of the async code. 🤔 |
Hey @andremralves, are you working on this? If not, I'd like to complete and land this with a little bit different approach. |
I'm not. I got a little bit stuck on this issue and was waiting for new ideas. Feel free to continue this work. 😁 |
Regarding the enabling fast API - one thing that I've noticed before in another PR is that once the fast API fallback to an exception-throwing slow path it could degrade the performance seriously so that it could be slower than not using fast API at all. I think some verification needs to be done to disprove this before we use fast API usage as an argument to throw errors in C++. |
Ref: nodejs/performance#111
The improvements are noticeable for cases where an error related to
mode
is thrown.Thanks to @anonrig for the idea.