-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
Include actual generated module specifiers in module specifier cache #44176
Include actual generated module specifiers in module specifier cache #44176
Conversation
Are you caching the actual package.json contents somewhere in here? If you are it isn't obvious from a glance at the code. Since it is very common to reference the same package from multiple importers, that would seem to be a worthwhile optimization if you are not. |
@dmichon-msft that would not be useful in this cache because this cache only exists for the file you’re currently editing—it gets cleared and recreated when you start requesting auto imports in another file, since so much of what’s stored depends on the location of the importing file. But caching these dependency package.jsons would be a good first step toward preserving work between auto imports in different files, and would use the same node_modules watch added here. I’ll look into that in a subsequent PR 👍 |
@sheetalkamat 8063299 shares the watches between projects as well as with the existing The watches are still “closed” upon clearing the cache, but since it’s shared with the closed script info watch, it’s now much less likely that closing these will result in the actual closing of the real underlying recursive watch. I’m open to finding a way to delay these |
} | ||
|
||
modulePaths ||= getAllModulePathsWorker(importingSourceFile.path, moduleSourceFile.originalFileName, host); | ||
const preferences = getPreferences(userPreferences, compilerOptions, importingSourceFile); |
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.
Should user preferences be part of the key for the cache as it does affect the module specifiers (esp what if compileOnSave with declarations enabled which uses module specifiers(? but not sure if same path applies) and auto import are inter mixed?)
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.
Only importModuleSpecifierEnding
and importModuleSpecifierPreference
affect the answers and I’m currently clearing it in editorServices.ts when they change... but it might be cleaner to make it part of the key. I’ll look and see how disruptive that is.
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.
Latest commit makes it part of the cache key instead of clearing when the host config changes. It has to be threaded through a lot more places, but it’s definitely more obvious that it’s a dependency, and will play nicer with other hosts/callers.
As part of #43149, I added a misnamed “module specifier cache,” which stopped short of actually caching final module specifiers, partly because that makes cache invalidation more complicated, and partly because the intermediate result that I was caching is sometimes used when we don’t actually need a final module specifier, but mainly because I didn’t realize just how worthwhile it would be to cache that final step. When experimenting with the feature more, I was disappointed that when requesting import statement completions at the exact same position twice in a row, the performance of the second call wasn’t that much better.
The problem is that the last uncached step of module specifier resolution for modules inside node_modules actually has to read the package’s package.json file for
types
andtypesVersions
, and this work was excluded from the cache. And it’s extremely likely to be re-done over and over even within a single import statement completion request, since most packages export more than one thing. The purple fringes at the bottom of this profile are all readingpackage.json
files inside node_modules. There are thousands of reads, even though there are only one or two dozen distinct package.json files. Basically, it was just a huge oversight on my part that we were redoing all this work.This PR takes the module specifier cache a step farther by adding final module specifiers to the cache, in addition to the intermediate results (arrays of
ModulePath
s) that were being cached previously. Doing this requires clearing the cache when resolution-affecting config settings change, as well as when any dependency’s package.json changes, which I’ve simplified to “when there are changes in node_modules.”Testing scenario
Dependencies
import c|
(cold cache) - 6446 entriesimport c|
(warm cache, same results)import a
(warm cache, different results) - 3855 entriesResults
Times are mean of 3 trials, elapsed time reported on
completionInfo
TS Server log.