Skip to content

perf(resolution): reuse exact-name local binding checks - #2871

Closed
luojiyin1987 wants to merge 1 commit into
colbymchenry:mainfrom
luojiyin1987:perf/exact-name-candidate-evaluation
Closed

luojiyin1987 wants to merge 1 commit into
colbymchenry:mainfrom
luojiyin1987:perf/exact-name-candidate-evaluation

Conversation

@luojiyin1987

Copy link
Copy Markdown
Contributor

A bare JS/TS call can check the same local binding for every exact-name candidate.
The helper memoizes its answer, but each call still builds a key and reads the cache.
matchByExactName() now stores that Boolean lazily for one invocation.
The filter position and candidate order stay the same.

The CodeGraph snapshot at 9c4794d6 reduces local-binding checks from 387,362 to 15,392.
Exact-name calls remain 123,724. Candidate visits remain 1,209,451.
Filtered candidates remain 52,544. Scoring calls remain 2,559.
Import candidates already leave the pool before ranking; this PR adds no import filter.

Validation

  • Eight focused tests cover zero, one, and multiple candidates, ties, file collisions, nested scopes, import aliases, bare JS/TS calls, and incremental sync.
  • The full suite passes: 739 test files and 8,473 tests. Existing conditions skip 17 files and 398 tests.
  • Three pinned repositories match after fresh indexing, symbol addition, modification, and deletion.
  • Both single-thread and two-worker resolution match. All 72 complete table comparisons match.
  • The comparison includes edge metadata, row IDs, and unresolved references. It normalizes only nodes.updated_at.

Five alternating pairs follow one warmup per arm and resolver mode.
Positive paired savings favor this branch.
CPU means process user time plus system time, including worker threads.

Mode Wall median, baseline → branch Wall sample variance, baseline → branch CPU median, baseline → branch CPU sample variance, baseline → branch
Single thread 27.503 → 25.929 s 2.021 → 1.068 s² 51.598 → 49.915 s 8.042 → 1.182 s²
Two workers 18.423 → 18.132 s 0.125 → 0.122 s² 56.410 → 56.139 s 1.261 → 0.847 s²

Median paired wall savings are 1.444 s with one resolver thread and 0.243 s with two workers.
The pooled batch-stage median changes from 12.726 s to 12.738 s.
An earlier execution period showed different timing directions.
The repeated-check reduction is confirmed. A stable whole-index speedup is not established.

Reproduce

  1. Build baseline 9c4794d694c62d343e43f29f2a76f576ed8b0e99 and this branch separately with npm ci && npm run build.
  2. Extract each repository at its pinned revision into a fresh directory with git archive.
  3. Use CodeGraph 9c4794d6, ESLint 5c8c2417, and validator.js ce010143 for the graph comparison.
  4. Run node --liftoff-only dist/bin/codegraph.js init --yes <fresh-directory> from each build.
  5. Compare complete nodes, edges, and unresolved_refs rows. Normalize only nodes.updated_at.
  6. Add a definition, modify it, and delete it. Run codegraph sync after each change and compare again.
  7. For timing, run five fresh CodeGraph indexes per arm and mode in AB, BA, AB, BA, AB order after warmups.
  8. Set CODEGRAPH_KERNEL=0 for both arms. Set CODEGRAPH_NO_PARALLEL_RESOLVE=1 for the single-thread mode.
  9. Set CODEGRAPH_RESOLVE_WORKERS=2 and CODEGRAPH_PARALLEL_RESOLVE_MIN=0 for the pooled mode.
  10. Measure wall time and process user plus system CPU time. Keep probes disabled during timing.

The benchmark uses Linux/WSL2, Node 24.15.0, WASM extraction, and --liftoff-only.
Only resolution uses the single-thread setting. Extraction can still use workers.
The default size limit skips five large CodeGraph files, including name-matcher.ts.
There are no Windows or macOS performance measurements.

Closes #2870. Related: #2829.

@luojiyin1987
luojiyin1987 marked this pull request as ready for review October 24, 2026 00:42
inth3shadows added a commit to inth3shadows/codegraph that referenced this pull request Oct 27, 2026
inth3shadows added a commit to inth3shadows/codegraph that referenced this pull request Oct 27, 2026
colbymchenry pushed a commit that referenced this pull request Oct 27, 2026
…ch — graph byte-identical

matchByExactName asked isLocallyBoundJsName for every cross-file
candidate of a bare JavaScript or TypeScript call, though the answer
depends only on the reference's name and file, which are the same for
every candidate. The helper memoizes it per file and name, but each
call still built the key and read the memo. The answer is now kept in
a lazy local for the one match, at the same place in the filter, so
candidates, order, scoring and confidence are untouched.

Validation: fresh indexes of codegraph's own source, excalidraw, vben,
express and zod dump byte-identical to main's (nodes, edges with their
metadata, unresolved refs, files), and express stays identical through
sync after a JS file is added, edited and deleted. A CPU profile of
indexing codegraph's own source (all threads, two runs per side) puts
isLocallyBoundJsName's self time at 150-173 ms on main and 45-46 ms
here; the scans it guards (bindsAtSites) are unchanged. Whole-index CPU
on vben, 10 interleaved runs, moves less than its noise. The PR's 8
tests pin the matcher's behaviour and pass here and on main.

Original PR #2871 by @luojiyin1987.
Fixes #2870

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@colbymchenry

Copy link
Copy Markdown
Owner

Thank you, @luojiyin1987! This landed as #2934 with you as the commit author: matchByExactName now reads a bare JS/TS call's local binding once per match instead of once per candidate. We confirmed the graph stays byte-identical on five repositories, through sync too, and a CPU profile shows the binding check's own time dropping by about 70% (about 0.1 s per index of CodeGraph's own source), so it went in without a CHANGELOG entry. It ships in the next release.

inth3shadows added a commit to inth3shadows/codegraph that referenced this pull request Oct 29, 2026
Brings 4955eac..787eafb (colbymchenry#3014, colbymchenry#3017, colbymchenry#3020, colbymchenry#3018, colbymchenry#3023). Clean
auto-merge. README: drop colbymchenry#2871 (closed upstream; colbymchenry#2934 merged in its
place, and name-matcher already matches upstream).
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.

perf(resolution): avoid repeated local-binding checks per exact-name match

2 participants