Skip to content

perf(resolution): read a bare JS/TS call's local binding once per match — graph byte-identical - #2934

Merged
colbymchenry merged 1 commit into
mainfrom
claude/pr-2871-exact-name-binding
Oct 27, 2026
Merged

colbymchenry merged 1 commit into
mainfrom
claude/pr-2871-exact-name-binding

Conversation

@colbymchenry

Copy link
Copy Markdown
Owner

Summary

A bare JavaScript or TypeScript call no longer asks, once per candidate, whether its own file binds the name locally. The answer depends only on the reference's name and file, so matchByExactName now keeps it in a lazy local for the one match. The graph is byte-identical.

Root cause

matchByExactName filters its exact-name candidates, and for a bare JS/TS call it drops every cross-file candidate when the calling file binds the name itself (a parameter, a const). That check, isLocallyBoundJsName(name, file), ran inside the per-candidate filter. It is memoized per file and name, so it never rescanned the file, but every candidate still built the memo key and read the memo. The issue measured 387,362 such checks on CodeGraph's own source, of which 15,392 were the first in their match.

What came from the contributor, and what we changed

From @luojiyin1987 (#2871, issue #2870): the lazy local in matchByExactName, read at the same place in the filter, and 8 tests that pin the matcher's behaviour (zero, one and tied candidates, a same-file winner, a parameter binding, import and member candidates, no carry-over between references, and nested scopes and import aliases through indexing and sync).

Ours: the commit message only. No CHANGELOG bullet: nothing a user can see changes, and no index-time difference shows above noise (below).

Validation

Byte identity (nodes, edges with their metadata, unresolved refs and files, by natural keys), main vs this change, fresh indexes: codegraph's own source, excalidraw, vben, express and zod are identical. express also stays identical through codegraph sync after a JS file is added, edited and deleted. That ran on 4c572e0; since matchByExactName itself changed on main afterwards (#1936), the five fresh indexes were repeated on 4eb8c2a with the change rebased onto it: identical again. Later main commits touch no code this change reads.

Tests: the PR's 8 pass, here and on main (they pin existing behaviour; nothing should change).

Cost. The saving is real but small. A CPU profile of a fresh index of CodeGraph's own source (all 17 threads, two runs per side, order alternated) puts isLocallyBoundJsName's self time at 150 and 173 ms on main and 46 and 45 ms with this change. bindsAtSites, the scan the memo guards, is unchanged (749/755 vs 702/784 ms), as is the rest of the index (about 130 s of sampled thread time either way). That is about 0.1 s per index here, below what whole-index timing can resolve: vben, 10 interleaved runs (5 in each order), median process CPU 30.5 s on main vs 31.3 s with the change, where whichever side runs second in a pair is about 0.65 s slower and the paired differences spread by about 1.4 s.

Suite on this commit (CODEGRAPH_KERNEL_EXPECT=1 npx vitest run --maxWorkers=4 --minWorkers=1, Windows): 763 files passed, 6 skipped; 9,079 tests passed, 85 skipped, 0 failed.

Fixes #2870

Lands #2871 by @luojiyin1987.

🤖 Generated with Claude Code

…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
colbymchenry merged commit 0174f80 into main Oct 27, 2026
@colbymchenry
colbymchenry deleted the claude/pr-2871-exact-name-binding branch October 27, 2026 18:32
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