vite icon indicating copy to clipboard operation
vite copied to clipboard

perf: async fs calls in resolve and package handling

Open patak-dev opened this issue 2 years ago • 7 comments

Description

getRealPath in resolve is taking ~8% of the workload in https://github.com/yyx990803/vite-dev-server-perf, and it is calling fs.realPathSync.native. After this PR, it takes ~2% by using fsp.realPath (equivalent to the .native sync version).

I tested the speed improvement using the test in the repo instead of the cpuprofile, but it isn't stable on my machine. I think that even if we now have a ton of promises being generated, the non-blocking fs calls should still make this change worth it. We need to test in some other benchmarks.

The PR also changes a fs.readFileSync in package.ts to be async, and that triggered a whole bunch of async/await changes in the codebase too.


What is the purpose of this pull request?

  • [ ] Bug fix
  • [ ] New Feature
  • [ ] Documentation update
  • [x] Other

patak-dev avatar Dec 01 '23 19:12 patak-dev

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

I don't know why Windows isn't happy (at least in CI) when using fsp.realPath. Using fs.realPathSync.native works, so for now we are back to sync for windows.

This makes this PR a bit more controversial, because it will mean a small regression on Windows due to the extra promises being generated. But a lot of them are needed due to the fsp.readFile change, and I ended up reducing the number of created promises at refactor: avoid creating promises in tryCleanFsResolve. So I think this may still be a good step.

If someone with more Windows knowledge finds a way to make fsp.realPath work, appreciated! But now we can also do that in another PR.

patak-dev avatar Dec 02 '23 22:12 patak-dev

@userquin tested in his Windows machine, and d3c8f90 is working for him with the same node version as CI. @sapphi-red, maybe you could try too when you have some time? Even if it works, I don't think we can just fallback to sync for CI 🤔

patak-dev avatar Dec 03 '23 11:12 patak-dev

It works on first run after build (pnpm test-serve), second run fails with same CI errors (node 20.10.0 LTS):

imagen

userquin avatar Dec 03 '23 11:12 userquin

I found a bug in Node (https://github.com/nodejs/node/issues/51031) and maybe that's the culprit. I pushed a commit to use fs.realpath.native instead of fsp.realpath.

sapphi-red avatar Dec 03 '23 12:12 sapphi-red

I found a bug in Node (nodejs/node#51031) and maybe that's the culprit. I pushed a commit to use fs.realpath.native instead of fsp.realpath.

Woah! Amazing find @sapphi-red 👏🏼 ❤️

I'm curious to see if this PR improves the benchmarks on your machine. I don't know why there is so much variance when I measure on mine.

patak-dev avatar Dec 03 '23 12:12 patak-dev

Here's the results of https://github.com/yyx990803/vite-dev-server-perf on my Windows machine. It's seems on a par.

before

1000 TS modules (50x20) loaded in: 1049ms (runs: [1274,1040,1060,1021,1049])
1000 TS modules (20x50) loaded in: 965ms (runs: [1008,934,946,966,965])
2000 TS modules (100x20) loaded in: 2237ms (runs: [2355,2252,2226,2237,2213])
5000 TS modules (250x20) loaded in: 5960ms (runs: [6592,6022,5874,5915,5960])
10000 TS modules (400x25) loaded in: 12265ms (runs: [13409,12106,12134,12265,12337])

after

1000 TS modules (50x20) loaded in: 1069ms (runs: [1257,1031,1051,1069,1071])
1000 TS modules (20x50) loaded in: 956ms (runs: [1033,956,971,941,946])
2000 TS modules (100x20) loaded in: 2249ms (runs: [2358,2249,2228,2191,2268])
5000 TS modules (250x20) loaded in: 5972ms (runs: [6610,5983,5936,5972,5927])
10000 TS modules (400x25) loaded in: 12152ms (runs: [13560,11932,11866,12162,12152])

I'm not sure why the "before" run is faster than the one in https://github.com/vitejs/vite/pull/15195#issuecomment-1837208126 though 🤔 .

sapphi-red avatar Dec 03 '23 13:12 sapphi-red