Skip to content

perf(index): definitions + subtypes store SymbolLoc — drop 173k per-entry Urls#209

Merged
Hessesian merged 2 commits into
refactor/unified-resolutionfrom
perf/f3-definitions-interning
Jul 8, 2026
Merged

perf(index): definitions + subtypes store SymbolLoc — drop 173k per-entry Urls#209
Hessesian merged 2 commits into
refactor/unified-resolutionfrom
perf/f3-definitions-interning

Conversation

@Hessesian

Copy link
Copy Markdown
Owner

Summary

F3 step 3: migrates definitions (the primary short-name lookup, 155,909 entries) and subtypes (16,801 entries) from DashMap<String, Vec<Location>> to Vec<SymbolLoc> — the same interning pattern PR #208 landed for qualified (FileId/FileTable, Location reconstituted only via FileTable::location at return boundaries).

  • Census-first: ~15 production readers found and converted (completion, go-def, references, resolver, jar enrichment); bare_name_cache rebuild is key-only and needed no change. Writers intern before taking the DashMap entry guard, matching perf(index): file interning — qualified drops 242k per-entry Urls for 20-byte SymbolLocs #208's lock-ordering.
  • Dedup semantics preserved exactly: the old l.uri==loc.uri && l.range==loc.range check is byte-equivalent to SymbolLoc{file,range} equality since file is interned from the same table — two distinct symbols at different ranges in the same file both survive.
  • remove_stale_for_uri's file-filtering compare is same-source/idempotent (interns the target URI, compares against already-interned entries) — the same ruling perf(index): file interning — qualified drops 242k per-entry Urls for 20-byte SymbolLocs #208's review made for the analogous case, re-verified here.
  • Cache unchanged: definitions/subtypes were never serialized — rebuilt at apply from file_data.symbols/supers — so CACHE_VERSION stays 29 and the existing on-disk cache loads unmodified.
  • Probe updated to the new shape; arithmetic reconciles (size_of::<SymbolLoc>() = 20 B × entry count).

Measured (same 117 MB / 12,621-file corpus)

before after
definitions 58.9 MB 9.5 MB
subtypes 5.2 MB 0.6 MB
accounted total 243.6 MB 189.6 MB
RSS apply peak 331 MB 274 MB

Cumulative since the plan started: warm-load peak 487 → 274 MB (−44%).

1440 tests green, clippy -D warnings clean, per commit. Task-scoped review: Approved — census independently verified complete by grep across all of src/, order/dedup semantics for the multi-hit map confirmed unchanged, no Critical/Important findings (one stylistic boundary-purity nit).

🤖 Generated with Claude Code

https://claude.ai/code/session_01EJsyQ1UgF8uJYR4HgpxEBB

Hessesian and others added 2 commits July 8, 2026 09:14
`definitions: DashMap<String, Vec<Location>>` held 155,909 `Location`s, each
carrying its own heap `Url` (104 B inline + the URI string) even though the same
file's URI already lives once in `file_table` (interned by PR #208 for
`qualified`). Store `Vec<SymbolLoc>` (4-byte `FileId` + range) instead.

Writers (apply.rs, jar.rs) intern each `Location` via the existing
`intern_location` helper at merge time; the transient `FileContributions` /
`LibraryBatch` builders keep building plain `Location`s and intern at flush,
mirroring `qualified`. Readers convert at the LSP return boundary via
`FileTable::location` (or `FileTable::url` where only the URI string is needed
for a further lookup). `remove_stale_for_uri` compares a single same-source
`FileId` (the removed file, re-interned idempotently), not a cross-source URI
string — no normalization divergence introduced.

Not serialized: `definitions` is rebuilt at apply from `file_data.symbols`, so
CACHE_VERSION is unchanged (stays 29).

Probe (real 117 MB corpus): definitions 58.9 MB → 9.6 MB (−49.3 MB); accounted
total 243.6 → 194.3 MB; warm-apply peak 331 → 278 MB. Full suite green
(1440 + 1 ignored), clippy -D warnings, fmt.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EJsyQ1UgF8uJYR4HgpxEBB
`subtypes: DashMap<String, Vec<Location>>` (the goToImplementation reverse index)
has a tiny reader surface — the single `subtypes_of` boundary returns
`Vec<Location>`; every feature (implementation, fill_when, traits) goes through
it. Apply the same `SymbolLoc` migration as `definitions`: writers intern at
merge (apply.rs, jar.rs), `subtypes_of` reconstitutes at the LSP boundary,
`reset_index_state` / `remove_stale_for_uri` filter by interned `FileId` /
`file_table.url`. Not serialized (rebuilt from `supers` at apply) — CACHE_VERSION
unchanged.

Probe: subtypes 5.2 MB → 0.6 MB (−4.6 MB); accounted total 194.3 → 189.6 MB.
Full suite green (1440 + 1 ignored), clippy -D warnings, fmt.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EJsyQ1UgF8uJYR4HgpxEBB
@Hessesian Hessesian merged commit 227d40d into refactor/unified-resolution Jul 8, 2026
4 checks passed
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