You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We have a rather large Typescript project, with both a lot of internal as well as external dependendencies.
I have more recently started looking into the rather sluggish initial "startup times" in our IDEs.
By "startup time" I mean the initial parsing etc. before intellisense etc. can kick in and show type information.
Activating tracing and checking times from VSCode the big block of finishCachingPerDirectoryResolution at the end immediatelly caught my eye.
Depending on the amount of dependencies a package/project has this can take upwards of 10 seconds.
After further investigation it really boils down to the initial call to watchFailedLookupLocationOfResolution (
is the main problem as for some reason, having many external dependencies can mean this array can grow beyond 100k entries.
Solutioning
First try
The first thing I was wondering is if I could simply use the watchOptions.excludeDirectories to avoid having so many watchers being set for at times irrelevant directories (irrelevant in the sense that i can guarantee they wont ever be needed to be watched), however this setting is simply ignored at this point.
Second try
I added a isIgnoredByWatchOptions inside the above mentioned for loop to avoid calling watchFailedLookupLocation for a location that should be ignored anyway. This did filter out calls, however did not make things faster.
To simply verify anything i added a !failedLookupLocation.includes('node_modules') to the check before calling isIgnoredByWatchOptions which brought down times roughly ~90%.
So i dug deeper into isIgnoredByWatchOptions and it looks like it is creating a rather expensive matcher every time it gets called, even if it basically gets called 100k times with the same matcher relevant parameters but a different path to check against.
Third try
I used the available memoizeCached to create a cached version of the regex creating found in the first lines of matchesExcludeWorker (
using this cached "excludeMatcher" approach together with watchOptions.excludeDirectories and checking isIgnoredByWatchOptions in the failedLookupLocations loop brought down time about 75% from ~8 seconds to 2 seconds.
Ask
My question is:
a) On a very basic level - why can there by so many (100k+) failed lookup locations and how can that be avoided
b) Is it ok to check if a failed lookup location is marked as "excluded" from watch options and check for that before watching it
c) Are you ok for me to raise a PR with the above solutioning to reduce time for the watcher setup?
π Motivating Example
Watcher setup time for larger projects has been reduced resulting in faster tsserver load times in IDEs
π» Use Cases
What do you want to use this for?
improve ide setup performance
What shortcomings exist with current approaches?
the current creating of matchers is creating performance issues when called a lot
What workarounds are you using in the meantime?
n/a
The text was updated successfully, but these errors were encountered:
π Search Terms
finishCachingPerDirectoryResolution
failedLookupLocation
β Viability Checklist
β Suggestion
System
Typescript 5.4
Context
We have a rather large Typescript project, with both a lot of internal as well as external dependendencies.
I have more recently started looking into the rather sluggish initial "startup times" in our IDEs.
By "startup time" I mean the initial parsing etc. before intellisense etc. can kick in and show type information.
Activating tracing and checking times from VSCode the big block of
finishCachingPerDirectoryResolution
at the end immediatelly caught my eye.Depending on the amount of dependencies a package/project has this can take upwards of 10 seconds.
After further investigation it really boils down to the initial call to
watchFailedLookupLocationOfResolution
(TypeScript/src/compiler/resolutionCache.ts
Lines 1146 to 1165 in 0dda037
In particular this loop:
TypeScript/src/compiler/resolutionCache.ts
Lines 1155 to 1157 in 0dda037
Solutioning
First try
The first thing I was wondering is if I could simply use the
watchOptions.excludeDirectories
to avoid having so many watchers being set for at times irrelevant directories (irrelevant in the sense that i can guarantee they wont ever be needed to be watched), however this setting is simply ignored at this point.Second try
I added a
isIgnoredByWatchOptions
inside the above mentionedfor
loop to avoid callingwatchFailedLookupLocation
for a location that should be ignored anyway. This did filter out calls, however did not make things faster.To simply verify anything i added a
!failedLookupLocation.includes('node_modules')
to the check before callingisIgnoredByWatchOptions
which brought down times roughly ~90%.So i dug deeper into
isIgnoredByWatchOptions
and it looks like it is creating a rather expensive matcher every time it gets called, even if it basically gets called 100k times with the same matcher relevant parameters but a different path to check against.Third try
I used the available
memoizeCached
to create a cached version of the regex creating found in the first lines ofmatchesExcludeWorker
(TypeScript/src/compiler/commandLineParser.ts
Lines 4010 to 4022 in 0dda037
using this cached "excludeMatcher" approach together with watchOptions.excludeDirectories and checking
isIgnoredByWatchOptions
in thefailedLookupLocations
loop brought down time about 75% from ~8 seconds to 2 seconds.Ask
My question is:
a) On a very basic level - why can there by so many (100k+) failed lookup locations and how can that be avoided
b) Is it ok to check if a failed lookup location is marked as "excluded" from watch options and check for that before watching it
c) Are you ok for me to raise a PR with the above solutioning to reduce time for the watcher setup?
π Motivating Example
Watcher setup time for larger projects has been reduced resulting in faster tsserver load times in IDEs
π» Use Cases
improve ide setup performance
the current creating of matchers is creating performance issues when called a lot
n/a
The text was updated successfully, but these errors were encountered: