-
-
Notifications
You must be signed in to change notification settings - Fork 6.4k
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
perf(resolve): improve file existence check #11436
Conversation
Hmm this fix isn't actually robust as we're checking owner file permissions only. I can't seem to find how nodejs checks if the current process has permission for the file. This StackOverflow answer sums up the issue. (EDIT: looks like the checks are done natively) |
Should we really take care of checking read permissions? |
@ArnaudBarre that is a good point, and I wonder why we didn't get a report yet for that. Maybe it is because it is extremely hard to debug. @bluwy I think that if we don't have read permission, then failing with a clear error is a better way to go. Just to be safe, maybe we should merge this PR for 4.1. |
If not generating errors improves performance, maybe we can consider using this import pathModule from 'path'
const binding = process.binding('fs')
function unsafeAccessSync(path, mode) {
const ctx = { path };
binding.access(pathModule.toNamespacedPath(path), mode, undefined, ctx);
return ctx.errno === undefined && ctx.error === undefined
} This function uses the internal binding and won't be guaranteed to work in every version. So we should run a test on every major version. But if it improves the performance significantly, I guess it's worth to do that. Also we can use |
I didn't know you can access internals like that 😲 I think it would be safer to avoid that for now, as Arnaud brought up a good point that we probably don't need to check read permissions when resolving. For other cases, we may still need it for correctness, but I checked that they're not hot paths so it may be fine. I'll make another commit to simplify the change and keep |
Tried this out on a large app, and unfortunately I didn't see a significant difference -- the runs I've posted show a small improvement, but I retried a few times and in some cases this PR was actually slower by a couple seconds. I don't see any way this change could have actually made things slower (I assume it was just natural variation on my own machine), but I'm definitely not seeing a consistent improvement: Using Vite 4.0.2initial loadreloadWith this PRinitial loadreloadI've attached the profiles for each load as well, in case they're helpful. |
Thanks for testing @davidwallacejackson! I checked the cpuprofiles and I can't quite tell what to improve as both seem to gave a different timeline. I can see lesser calls to |
Didn't check myself but I think having esbuild as bottleneck seems more expected than fs.access. And probably can make bigger difference on Windows where FS is often slower. |
Yeah I think we need to investigate further on the esbuild part, but besides that I think this PR is good to go for now for 4.1. |
): string | undefined { | ||
if (isFileReadable(file)) { | ||
if (!fs.statSync(file).isDirectory()) { | ||
const stat = fs.statSync(file, { throwIfNoEntry: false }) |
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 know vite a lot but this not being in a try catch could be an issue as it would throw an error for virtual modules
See this error an Astro user encountered, seems like caused by this change
Description
7x perf improvement for
tryFileResolve
file existence check (NOTE: through testing this does not translate to faster preceivable performance)One of the drawbacks of
fs.accessSync
to check file readable is that it errors if the file doesn't exist. node takes time to generate the errors that we don't use. This PR callsstatSync
and check readability ourselves, skipping any error generation.Additional context
Thanks @ArnaudBarre for providing the flamegraph of initial server run.
Here's a gist comparing different ways to check file existence.
fs.existsSync
is the fastest but it doesn't check for readability, using this PR the perf numbers are actually still quite close tofs.existsSync
.What is the purpose of this pull request?
Before submitting the PR, please make sure you do the following
fixes #123
).