-
-
Notifications
You must be signed in to change notification settings - Fork 219
perf: rework snapshot hot paths #2852
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
Conversation
🦋 Changeset detectedLatest commit: 6558687 The changes in this PR will be included in the next version bump. This PR includes changesets to release 2 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
862453c
to
2cfcfbd
Compare
It's possible when one file is a For the possible bug with "fileNameWithoutEnding", it's more of an "overly aggressive" cache invalidation. We might have to think more about if there are other cases where the new check doesn't cover. |
hmm, you are right. there must be something we can do here though. the current keying means a large project repeatedly resolves the same module many times. this usually involves file system calls too, which is what takes so long (since ts' own resolveModule hits the file system for path resolution). i didn't encounter a directory cache, can you point me at the code you're talking about?
extremely aggressive cache invalidation 😅 quite a lot of files will overmatch. what if i have short filenames like |
The
|
do we?
given the current logic before this PR: language-tools/packages/language-server/src/plugins/typescript/module-loader.ts Lines 69 to 73 in dec37ea
a key might be if we're deleting caches for for example, if we had this cache:
we will clear all the
we don't clear the per directory cache edit: ok cool you realised this 😂 |
FYI im not encountering any issue, and don't have any obvious reproduction i decided to profile if you want more info you're probably better off chatting to me on discord about it or something as this is the result of reading through a whole bunch of CPU profiles using shadcn-svelte as a test subject |
You're saying it improves the performance of svelte-check and not the watch mode, right? Then I think it's better to make it not call |
yes i'm solely profiling if we can avoid calling it altogether, great 😄 i can revert the key change for now. can you explain a bit more where you think we can avoid calling the deletion function, and why? |
Re key: Could we only use the filename if we detect the file name ending is |
FYI i have discarded the key change for now and got rid of a bit of garbage collection around diagnostic iteration we could possibly merge this one as-is when we're happy and work on the key stuff in a follow up i would like to figure it out since it seems we invalidate caches far too often right now doing something with extensions makes sense to me Edit: I'll fix the tests when I'm next at a laptop 👍 |
ok ive reverted the we should land #2853 first and ill sort conflicts |
**`fromNonSveltePath`** This function was originally using `replace` to unix-ify paths before then testing against them with `endsWith`. We can instead use static patterns on the unaltered path regardless of separator. **`getLastPartOfPath`** This now uses `slice` on the last separator rather than splitting only to retrieve the last part.
Reverts the `getKey` change and updates diagnostics iteration to avoid allocating an array we later discard.
816ddc4
to
b856e36
Compare
i've rebased @dummdidumm and this now only contains the additional smaller optimisations (they each still save us garbage collection though so worth having) |
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.
thank you for starting this work and nudging us towards these perf improvements!
no worries! i just pushed a quick prettier change since it wanted single quotes in the changeset |
fromNonSveltePath
This function was originally using
replace
to unix-ify paths beforethen testing against them with
endsWith
.We can instead use static patterns on the unaltered path regardless of
separator.
deleteUnresolvedResolutionsFromCache
This was originally using
split
to "parse" the cache key into afile/specifier pair.
We don't actually need to do this as we know there's always one
occurrence of
CACHE_KEY_SEPARATOR
. So we can instead justslice
onthe index of the separator.
Additionally, we only compute any of this the first time we encounter an
unresolved cache entry.
Possible bug
I then noticed that
fileNameWithoutEnding
could bea
(froma.svelte
), for example. This then meant we would delete all cacheentries with specifiers containing
a
(since we didspecifier.includes(fileNameWithoutEnding)
).I have changed this to explicitly test for these two cases instead:
fileNameWithoutEnding
)/{fileNameWithoutEnding}.
)For example,
a.svelte
would becomea
. We then want to check for/a.
to be able to match/a.svelte
,/a.svelte.js
, etc. Nobody canimport it without a
/
preceding it since then it'd be a barespecifier.
getLastPartOfPath
This now uses
slice
on the last separator rather than splitting onlyto retrieve the last part.
diagnostics
In the root svelte-check logic, we were previously allocating an array of the diagnostics from various sources then later discarding that array (garbage collecting it).
I have changed this to instead iterate through each diagnostics set one by one, so we never allocate a new array.
Why, James?
Locally this reduces
svelte-check
in shadcn-svelte's own docs from ~14s to ~10s.Most of this is the change in keying strategy (
getKey
), but the lazy name computation helped a lot too.