Skip to content

fix(check-types): read each file's version once per check - #16

Open
cray0000 wants to merge 1 commit into
masterfrom
check-types-script-version-cache
Open

cray0000 wants to merge 1 commit into
masterfrom
check-types-script-version-cache

Conversation

@cray0000

Copy link
Copy Markdown
Member

What and why

check-pug-types was slow on large projects. The language service asks for the version of every project file on each per-file diagnostics call, and getScriptVersion stat'ed the file on each of those calls, so a check made O(files²) fs.statSync calls.

A CPU profile of a 185 s run on a 2,250-file project showed about 84 s of self time in fs.statSync alone, plus about 25 s more in fs utilities, all under host.getScriptVersion. The actual type checking was a small part.

The fix memoizes each file's version per language service: a Map inside createLanguageServiceFromTsconfig.

Measured (same 2,250-file project, macOS, a loaded machine, so noisy)

Wall time
0.1.18 102 s, 160 s, 186 s
With this change 49 s (first, under load), then 19 s, 20 s, 27 s

The output is byte-identical: the same 10 diagnostics, and the diff of the two outputs is empty.

Behaviour notes

  • The cache lives in one language service, with no state on disk, so branch switches and worktrees are unaffected.
  • A file edited during a running check isn't re-read. That doesn't matter for a one-shot CLI.
  • createLanguageServiceFromTsconfig is exported. A caller that keeps the service alive across edits must create a new one to see changed files; a code comment says so. No caller in this repo does.

Tests

  • New unit test, reads each file version once per check, not once per diagnosed file. It counts ts.sys.getModifiedTime calls per file over a full check of example/:
    • 0.1.18: up to 11 calls for one file;
    • with the fix: exactly 1.
  • npx vitest run packages/check-types/test/unit/index.test.ts: 12/12 pass. I checked that the new test fails without the fix.
  • Not run: the full npm test (VS Code and vendored suites).

No version bump: publishing goes through lerna publish patch as usual.

🤖 Generated with Claude Code

The language service asks for the version of every project file on each
per-file diagnostics call, and getScriptVersion stat'ed the file every
time: O(files²) stats. On a 2,250-file project that was most of a
100–186 s check. Caching the version per service makes it about 20–27 s
with byte-identical output.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant