Skip to content

Commit 9f775ad

Browse files
authored
fix(perf): pass symbolsOnly through parseFilesWasmInline (#1489)
* chore: gitignore napi-generated artifacts in crates/codegraph-core * chore(tests): remove unused biome suppression in visitor.test.ts * fix(titan-run): sync --start-from enum and phase-timestamp list with actual phases * fix(hooks): track Bash file modifications via before/after git status diff Adds snapshot-pre-bash.sh (PreToolUse Bash) + track-bash-writes.sh (PostToolUse Bash): the pre-hook captures git status --porcelain to a per-worktree temp file before each Bash call; the post-hook diffs the before/after state and appends newly modified or created files to .claude/session-edits.log. This closes the gap where files written by sed -i, printf redirects, tee, heredocs, or build tools (Cargo.lock, lockfiles) were never recorded, causing guard-git.sh to emit false-positive BLOCKED errors. Closes #1457 * chore(native): remove dead code (unused var, method, variant, fields) - clojure.rs: annotate lifetime-anchor assignment to silence false-positive - cfg.rs: remove never-called start_line_of method - complexity.rs: remove never-constructed NotHandled variant; convert irrefutable if-let patterns to plain let destructures - dataflow.rs: remove never-read callee fields from CallReturn/Destructured - incremental.rs: remove never-read lang field from CacheEntry cargo check and cargo clippy both clean after these changes. * refactor(native): extract emit_pts_alias_edges params into PtsAliasCtx struct * fix(wasm): sort call targets by confidence before emit to match native engine * fix(bench): add 2 warmup runs and raise INCREMENTAL_RUNS to 5 for incremental tiers * ci(bench): add per-PR perf canary for extractor/graph/native changes Adds .github/workflows/perf-canary.yml — a path-filtered workflow that fires on PRs touching src/extractors/, src/domain/graph/, or crates/** and runs only the incremental-benchmark suite (full build + no-op + 1-file rebuild, both engines). Catches the class of regressions that accumulated invisibly across the Phase 8.x PRs and were only detected at v3.12.0 publish time. The regression guard gains BENCH_CANARY=1 mode: raises thresholds to 50%/100%/150% (standard/noisy/WASM) and skips the build, query, and resolution suites — only incremental checks run. This absorbs shared- runner timing variance while still blocking catastrophic regressions (+98% full build, +1827% 1-file rebuild from v3.12.0). Closes #1433 * fix(perf): plumb symbolsOnly through parseFilesWasmInline to skip analysis visitors * fix(perf): add parser.ts to canary paths and free WASM tree on symbolsOnly inline path Guard the inline-path optimization against regressions by adding src/domain/parser.ts to the perf-canary paths filter — without it the canary silently skips exactly the file this PR modifies. Also free the WASM-backed tree when symbolsOnly=true in parseFilesWasmInline. The tree was being parsed and then discarded without an explicit .delete() call, leaking WASM linear memory on every incremental rebuild that triggers the inline path. The deletion is guarded by a typeof check, matching the pattern used by the extractor-error path at line 1078.
1 parent 65bd28a commit 9f775ad

2 files changed

Lines changed: 20 additions & 3 deletions

File tree

.github/workflows/perf-canary.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ on:
1919
paths:
2020
- "src/extractors/**"
2121
- "src/domain/graph/**"
22+
- "src/domain/parser.ts"
2223
- "crates/**"
2324
- "scripts/benchmark.ts"
2425
- "scripts/incremental-benchmark.ts"

src/domain/parser.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1198,11 +1198,16 @@ const INLINE_BACKFILL_THRESHOLD = 16;
11981198
*
11991199
* Returns symbols with `_tree` set so `runAnalyses` can run AST/CFG/dataflow
12001200
* visitors via the unified walker (mirrors how WASM-engine results behaved
1201-
* before the worker pool was introduced).
1201+
* before the worker pool was introduced), unless `symbolsOnly` is true — in
1202+
* that case `_tree` is not set, skipping all analysis visitor walks. Use
1203+
* `symbolsOnly` when only definitions/calls/typeMap are needed (e.g. the
1204+
* this/super dispatch post-pass) to avoid the analysis overhead on the inline
1205+
* path, matching the optimization already applied to the worker-pool path.
12021206
*/
12031207
async function parseFilesWasmInline(
12041208
filePaths: string[],
12051209
rootDir: string,
1210+
symbolsOnly = false,
12061211
): Promise<Map<string, ExtractorOutput>> {
12071212
const result = new Map<string, ExtractorOutput>();
12081213
if (filePaths.length === 0) return result;
@@ -1220,7 +1225,18 @@ async function parseFilesWasmInline(
12201225
if (!extracted) continue;
12211226
const relPath = path.relative(rootDir, filePath).split(path.sep).join('/');
12221227
const symbols = extracted.symbols as ExtractorOutput & { _tree?: unknown; _langId?: string };
1223-
symbols._tree = extracted.tree;
1228+
// When symbolsOnly=true, skip setting _tree so runAnalyses does not run
1229+
// AST/complexity/CFG/dataflow visitor walks — only definitions/calls/typeMap
1230+
// are needed by callers like the this/super dispatch post-pass.
1231+
if (!symbolsOnly) {
1232+
symbols._tree = extracted.tree;
1233+
} else if (typeof (extracted.tree as any)?.delete === 'function') {
1234+
// Free the WASM-backed tree immediately — web-tree-sitter trees are backed
1235+
// by WASM linear memory and require explicit disposal. When symbolsOnly is
1236+
// true the tree is never stored anywhere, so we must delete it here to
1237+
// avoid leaking WASM heap on every incremental rebuild.
1238+
(extracted.tree as any).delete();
1239+
}
12241240
symbols._langId = extracted.langId;
12251241
result.set(relPath, symbols);
12261242
}
@@ -1246,7 +1262,7 @@ export async function parseFilesWasmForBackfill(
12461262
opts: { symbolsOnly?: boolean } = {},
12471263
): Promise<Map<string, ExtractorOutput>> {
12481264
if (filePaths.length <= INLINE_BACKFILL_THRESHOLD) {
1249-
return parseFilesWasmInline(filePaths, rootDir);
1265+
return parseFilesWasmInline(filePaths, rootDir, opts.symbolsOnly);
12501266
}
12511267
return parseFilesWasm(filePaths, rootDir, opts.symbolsOnly ? EXTRACT_ONLY : FULL_ANALYSIS);
12521268
}

0 commit comments

Comments
 (0)