Make --build --watch iterations reuse programs (30s → ~2s per file change)#1200
Open
NullVoxPopuli wants to merge 2 commits into
Open
Make --build --watch iterations reuse programs (30s → ~2s per file change)#1200NullVoxPopuli wants to merge 2 commits into
--build --watch iterations reuse programs (30s → ~2s per file change)#1200NullVoxPopuli wants to merge 2 commits into
Conversation
tsc -b --watch reconstructs each project's Program from scratch on every file change: the solution builder unconditionally releases built programs (afterProgramDone -> releaseProgram()), its compiler host has no SourceFile cache across iterations, and volar's proxyCreateProgram keeps its language/snapshot/resolution caches in a single slot that any multi-project solution thrashes. For a 19,286-file project a one-line change cost 30s (Parse 7.3s, ResolveModule 7.2s, Check 0.14s); with these patches the same iteration costs ~2s, identical to plain --watch. Three source patches (same playbook as the existing proxyCreateProgram / tryGetJSExtensionForFile patches, loud errors if dep shapes change): - afterProgramDone: retain programs in watch mode so oldProgram reuse engages (~+1.4GB RSS on the 19k-file project). - setGetSourceFileAsHashVersioned: version-validated SourceFile cache, scoped per project (redirect files must not be shared across programs). - tryAddRoot: with a partially reused program, source-of-project-reference redirect files can lose their include-reasons keying during buildinfo emit; files without reasons cannot be roots, so skip them. - proxyCreateProgram: key volar's caches per configFilePath. Tracking: #1199, upstream volarjs/volar.js#314 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Important
made with claude
I'm not an expert in this codebase, and could be way off base, and I apologize if this is a waste of time / completely wrong
Fixes #1199 (upstream: volarjs/volar.js#314).
In a TS project-references monorepo (59 composite projects, 19,286-file app), a one-line change under
ember-tsc --build --watchtook ~30s to report — the same cost as the project's initial cold build. Plain--watchon the same project: ~2s.-b --watch--watchWhy it was slow (three compounding causes, proven by instrumentation)
afterProgramDone→releaseProgram()), even in watch mode — sooldProgramnever reachescreateProgramand SourceFile/resolution reuse is impossible.parsedSourceFilesWeakMap, so every.gtsre-transforms.proxyCreateProgramkeeps its language/snapshot/moduleResolutionCachestate in a single slot keyed on the last options — any multi-project-bsolution thrashes it every iteration.The patches
Same playbook as the existing
proxyCreateProgram/tryGetJSExtensionForFilesource patches inrun-volar-tsc.ts(exact-shape matching, loud error if the dep changes — verified matching on both TS 5.9.3 and 6.0.3):afterProgramDone: keep programs alive in watch mode (~+1.4GB RSS on the 19k-file project).setGetSourceFileAsHashVersioned: version-validated SourceFile cache, scoped per project — with project references the same physical file is a redirect in one program and a root in another, so SourceFile objects must never be shared across projects (sharing them crashes buildinfo emit).tryAddRoot: with a partially reused program, source-of-project-reference redirect files can lose theirfileIncludeReasonskeying and buildinfo emit crashed (Cannot read properties of undefined (reading 'some')). A file without include reasons can't be a RootFile, so skipping it is the correct result.proxyCreateProgram: key volar's caches perconfigFilePath.Tests
New
build-watch-mode.test.ts+ a two-project fixture (composite emitter +noEmit/incrementalconsumer importing the emitter's source through a project-reference redirect — the exact shape that crashed). Spawns--build --watch, asserts diagnostics appear and clear across iterations against a reused program, no crash. Existing build-mode tests still pass (6/6 ints-extensionless-app); the 5 failing language-server tests inpackage-test-corefail identically onmain(pre-existing, CLI path untouched).🤖 Generated with Claude Code