Skip to content

refactor(core): drop redundant per-call FileId/path indices in detectors#357

Merged
BartWaardenburg merged 2 commits into
mainfrom
perf/issue-333-detector-hoists
May 12, 2026
Merged

refactor(core): drop redundant per-call FileId/path indices in detectors#357
BartWaardenburg merged 2 commits into
mainfrom
perf/issue-333-detector-hoists

Conversation

@BartWaardenburg
Copy link
Copy Markdown
Collaborator

Summary

Removes four redundant per-call hash-map builds in crates/core/src/analyze/:

  • reachable_files: FxHashSet<u32> in find_unused_exports
  • module_by_id: FxHashMap<FileId, &ModuleNode> in find_private_type_leaks
  • module_idx_by_file_id: FxHashMap<FileId, usize> in find_duplicate_exports
  • file_id_by_path: FxHashMap<&Path, FileId> in find_duplicate_exports

FileIds are assigned sequentially in crates/core/src/discover/walk.rs:264 after path-sorting, so graph.modules[file_id.0 as usize] is correct. This is the same pattern find_unused_files already uses at crates/core/src/analyze/unused_files.rs:73. The maps were doing redundant work.

Net: -79 +41 lines on a single file.

Behavior

No change. Issue counts identical on benchmarks/fixtures/real-world/next.js (24986 issues, BEFORE and AFTER).

Timing

Wall-clock is in-the-noise across five fixtures (warm cache, multiple runs):

Fixture Files BEFORE AFTER
next.js 125k 1.66–1.79s 1.65–1.77s
typescript 44k 1.14–1.19s 1.10–1.22s
vite 24k 0.35–0.50s 0.33–0.39s
vue-core 12k 0.07–0.10s 0.07s
svelte 11k 0.42–0.46s 0.43–0.45s

Per issue #333's acceptance criterion: "ships as a pure structural cleanup if the timing is in-the-noise."

Test plan

  • cargo test --workspace --all-targets (37 test suites green)
  • cargo clippy --workspace --all-targets -- -D warnings (clean)
  • cargo fmt --all -- --check (clean)
  • cargo doc --workspace --no-deps --document-private-items (clean)
  • Issue-count parity verified on next.js JSON output
  • rust-reviewer APPROVE (one cosmetic nit, rustfmt-compliant)

Fixes #333

find_unused_exports, find_private_type_leaks, and find_duplicate_exports
each rebuilt a FxHashMap (reachable_files set, module_by_id,
module_idx_by_file_id, file_id_by_path) on every invocation. FileIds are
assigned sequentially in discover/walk.rs:264, so graph.modules can be
indexed directly via file_id.0 as usize, the same pattern find_unused_files
already uses at unused_files.rs:73.

Real-world wall-clock is in the noise across next.js (125k files),
typescript (44k), vite (24k), vue-core (12k), and svelte (11k). Issue
counts on next.js identical (24986). Shipped as the structural-cleanup
branch of the issue's acceptance criterion.

No behavior change.

Fixes #333
Follow-up to 6349779 addressing panel-review feedback:

1. Document the invariant on ModuleGraph::modules: modules[file_id.0 as
   usize].file_id == file_id, anchored to discover/walk.rs and
   build::populate_edges. Single source of truth instead of duplicating
   the rationale in three detector comments.

2. Add debug_assert_eq! at each of the four index-by-FileId sites
   introduced in the parent commit (find_unused_exports cross-file ref
   check, find_private_type_leaks module lookup, find_duplicate_exports
   enumerate, collect_dynamic_reexport_sources wrapper lookup). Fires
   under cargo test if a future ModuleGraph::build change ever filters
   or sparsifies modules silently. Zero cost in release.

3. Confirmed issue-count parity on all five real-world fixtures (was
   verified on next.js only in the parent commit): next.js 24986,
   typescript 14622, vite 1582, vue-core 239, svelte 4855, identical
   BEFORE/AFTER.

Refs #333
@BartWaardenburg BartWaardenburg merged commit cd4c311 into main May 12, 2026
19 checks passed
@BartWaardenburg BartWaardenburg deleted the perf/issue-333-detector-hoists branch May 12, 2026 18:12
@BartWaardenburg
Copy link
Copy Markdown
Collaborator Author

Released in v2.73.0.

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.

Audit detectors for per-invocation recomputed work (follow-up to #322 task 1)

1 participant