perf(index): definitions + subtypes store SymbolLoc — drop 173k per-entry Urls#209
Merged
Hessesian merged 2 commits intoJul 8, 2026
Merged
Conversation
`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
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.
Summary
F3 step 3: migrates
definitions(the primary short-name lookup, 155,909 entries) andsubtypes(16,801 entries) fromDashMap<String, Vec<Location>>toVec<SymbolLoc>— the same interning pattern PR #208 landed forqualified(FileId/FileTable,Locationreconstituted only viaFileTable::locationat return boundaries).bare_name_cacherebuild 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.l.uri==loc.uri && l.range==loc.rangecheck is byte-equivalent toSymbolLoc{file,range}equality sincefileis 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.definitions/subtypeswere never serialized — rebuilt at apply fromfile_data.symbols/supers— so CACHE_VERSION stays 29 and the existing on-disk cache loads unmodified.size_of::<SymbolLoc>() = 20 B× entry count).Measured (same 117 MB / 12,621-file corpus)
Cumulative since the plan started: warm-load peak 487 → 274 MB (−44%).
1440 tests green, clippy
-D warningsclean, per commit. Task-scoped review: Approved — census independently verified complete by grep across all ofsrc/, 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