…rty cache
A non-partial property created by a lookup without the function property
augment was also copied into the augmented cache. An augmented lookup
that misses its own cache now reads it from the other cache instead, which
gives the same symbol in every order of lookups: the augmented cache is
still consulted first, and partial properties are still recreated. Cache
maps are allocated on their first store instead of on the first lookup.
Nothing else reads the caches.
38k-file program (37,943 files), median of 3, single threaded / 4
checkers, symbols/types/instantiations unchanged. On main: heap after
check 14.03 -> 13.84 GB (-1.4%) / 21.25 -> 20.96 GB (-1.4%), allocations
148.86M -> 147.86M / 246.89M -> 245.02M. On top of the lazy member PRs
and their follow-ups: heap 10.36 -> 10.23 GB (-1.3%) / 15.07 -> 14.84 GB
(-1.5%), allocations 149.24M -> 148.42M / 248.70M -> 247.09M.
Prototype in a Rust port of the checker (4 checkers there assign files
by directory locality): 2,369,096 / 3,391,408 cache entries avoided,
70,673 / 77,947 augmented lookups served from the other cache, -0.11 /
-0.13 GB.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
getUnionOrIntersectionProperty keeps two caches per union/intersection type, one with and one without the function property augment. when a lookup without the augment creates a property that isn't partial, it also copies it into the augmented cache. the copy is only ever read by a later augmented lookup of the same name, which can read it from the other cache instead. also, ast.GetSymbolTable allocates a cache map on the first lookup, even when nothing ever gets stored
this reads the non-augmented cache on an augmented miss (non-partial entries only, like the copy) and allocates a cache on its first store. lookups return the same symbol in any order:
nothing else reads these caches
on our 38k-file program (37,943 files, 0 errors), median of 3, one process at a time:
symbols, types and instantiations don't change (25,972,751 / 9,639,290 / 44,879,960 on main single threaded). heap is Memory used from --extendedDiagnostics (live heap after GC; spreads by under 0.01 GB between runs single threaded, up to 0.15 GB with 4 checkers), allocs is Memory allocs. check time is within noise
per path (counted in an instrumented port of the checker with the same change, on that stack): 2.37M fewer cache entries single threaded (3.39M with 4 checkers), and 70,673 augmented lookups are served from the other cache
same diagnostics on every run. go test ./... passes (except the macOS fsevents tests in internal/fswatch, which time out here under load and pass on a rerun), the testrunner also with TS_TEST_PROGRAM_SINGLE_THREADED=false, lint and format are clean. no new test, the change has no observable effect besides memory
used claude code to help write this, ive reviewed it