perf(lsp): Don't retain SourceFileObject
s in sourceFileCache
longer than necessary
#23258
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
The TS language service requests source files via getSourceFile. In that function, we unconditionally add the source file to our sourceFileCache. The issue is that we only remove things from that cache if the source file becomes out of date. For files that don't get changed, we keep them in the cache indefinitely. So sometimes we keep SourceFile objects from being GC'ed because they're retained in our cache, even though TS doesn't refer to them any more. I see this in pretty much all of the heap snapshots I've taken.
The fix here is pretty direct - just store weak references to the sourcefiles in the cache. It doesn't really change our caching behavior, it just prevents us from being the only retainer of a
SourceFile
. I also split thesourceFileCache
into a separate cache just for assets, as we rely on those being alive.The simpler fix is to only cache assets, but presumably that has a perf impact.
In local testing, this PR reduced the size of the JS heap by about 1 GB when using
deno lsp
in the Typescript repo.