Avoid expensive incremental reconciliation after dependency paths move - #4865
Avoid expensive incremental reconciliation after dependency paths move#4865John Favret (johnfav03) wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a heuristic to avoid costly incremental reconciliation when dependency paths move.
Changes:
- Detects replaced reference targets and large reverse-dependency closures.
- Resets eligible snapshots to cold-build state.
- Adds a pnpm symlink regression scenario and baseline.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
internal/execute/incremental/programtosnapshot.go |
Implements detection and cold-state fallback. |
internal/execute/tsctests/tsc_test.go |
Adds the incremental pnpm scenario. |
internal/execute/tsctests/sys.go |
Adds a symlink-update test helper. |
testdata/baselines/reference/tsc/incremental/pnpm-dependency-version-change-moves-resolved-paths.js |
Records expected incremental behavior. |
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
|
Can you split this into two commits too? This also seems a bit heuristic-y and a lot of code, not exactly sure how to make sure it's sound. |
8749a69 to
a8d48ff
Compare
|
Just split the changes into two commits. The difference is clear in |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.
Suppressed comments (1)
internal/execute/incremental/programtosnapshot.go:200
- This early return leaves composite projects on the expensive reconciliation path even when every condition listed in the PR description is met. Composite projects can also resolve dependencies through moved pnpm paths, but the stated scope does not exclude them. Either support a cold-equivalent reset for composite snapshots, or explicitly narrow the PR's scope and add a rationale/test for why composite state cannot be reset safely.
if t.oldProgram == nil || t.snapshot.options.Composite.IsTrue() {
Fixes microsoft/TypeScript#63731
When a dependency version change moves its resolved files to new paths, unchanged source files can have their reference targets replaced. The incremental builder previously reconciled this as an ordinary file change, which could lead it to compute a declaration shape signature and propagate possible shape changes through reverse dependencies. When this replacement impacts most of the program, reconciling is more expensive than a cold build - in the linked issue, the post-change incremental run performed more instantiations and took significantly longer than a cold build.
To fix this, we detect reference target replacement, and create a cold-build equivalent snapshot state when these conditions are met: