Skip to content

perf(go): Walk once and resolve calls in parallel - #159

Open
thedrow wants to merge 10 commits into
iepathos:masterfrom
thedrow:perf/go
Open

thedrow wants to merge 10 commits into
iepathos:masterfrom
thedrow:perf/go

Conversation

@thedrow

@thedrow thedrow commented Oct 18, 2026 •

Copy link
Copy Markdown

Summary

Go analysis walks each function once, then resolves calls in parallel. This branch sits on perf/common (#155) and targets master.

Changes

perf(go): Walk each function once

Metrics, purity, and advanced checks each walked a function's syntax tree. They are now per-node visitors driven by one shared traversal.

perf(go): Resolve calls in parallel

  • Each Go source is read once and shared by framework evidence, import aliases, and the symbol index.
  • Handler detection scans only lines that can register a handler.
  • Package import paths are computed once per directory.
  • Caller resolutions run in parallel and are added in caller order.

Test plan

  • just test
  • debtmap analyze on a Go checkout and confirm the JSON matches master aside from timestamps

Made with Cursor

How to stack these

These pull requests target master. From a clone of iepathos/debtmap:

gh stack link 155 156 159 161 160
gh stack merge

perf/common is #155. Then #156 Rust, #159 Go, #161 Solidity, and #160 TypeScript. The last three contain #155 and do not contain each other. gh stack merge 156 stops after Rust.

Module structure dependency edges are now collected in sorted
order, so reports no longer depend on hash iteration order.
Node text, position and traversal helpers were copied in each
tree-sitter analyzer. They now live in analyzers::syntax_tree,
together with a single-pass walker for per-node visitors.
- Call graph maps use foldhash.
- FunctionId hashes only the file name of its path; equal ids
  still hash equally.
- Successful path canonicalizations are cached.
- Uncertain calls are kept in a BTreeSet instead of a sorted
  vector with quadratic inserts.
- Effect provenance shares its owner id through Arc.
- The unified analysis and data flow graph share one call graph
  through Arc instead of each holding a clone.
- Call graph builders take the graph with mem::take.
- Purity propagation borrows the graph, analyzes starting purity
  in parallel, and borrows propagated assessments.
- The final analysis is dropped on a background thread after
  output is written.
- Entropy counts token windows by interned ids and builds patterns
  only for repeated windows.
- Suppression regexes are compiled once per comment style, and
  suppression comments are parsed during the parallel file read.
- Coupling metrics index dependents in one pass.
- Duplicate chunks are grouped by a precomputed hash.
- God object items are planned in parallel and applied in file
  order.
God-object scope collection sorted every function id once per
item. Keep one sorted list, invalidate it when a new id is
inserted, and binary-search the functions in one file.
File cohesion scanned every function and sorted every edge
once per file. Look up ids in the sorted cache and read call
counts built once per graph.
Parse-error checks, child lists, and tree walks were still copied
beside the shared syntax tree helpers.
Metrics, purity and advanced checks of a Go function each walked
its syntax tree separately. They are now per-node visitors driven
by one shared traversal.
- Each Go source is read once and shared by framework evidence,
  import aliases and the symbol index.
- Handler detection scans only lines that can register a handler.
- Package import paths are computed once per directory.
- Caller resolutions run in parallel and are added in caller
  order.

This branch has not been deployed

No deployments
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.

1 participant