perf(scan): parse/read files once, parallelize sections, scope cache#24
Merged
Conversation
Cuts redundant work in the scan engine and fixes a latent clone-cache bug. - Walk, read, and Go-parse each file once per scan via a shared fileCorpus (runner/support/corpus.go); quality and design reuse one AST through support.ParseGoSource instead of re-parsing. - Run enabled sections on a NumCPU-bounded worker pool with deterministic, position-indexed result ordering. ScanCache and ArtifactStore are now mutex-guarded and OnSectionComplete is serialized. - Scope the per-file cache fingerprint per config family (cache v7) so unrelated config edits (output format, target names, excludes) no longer invalidate the whole cache. - Clone detection: partition candidates by (LeftDoc,RightDoc) so the overlap merge is no longer O(C^2), and normalize document paths once for sorting. - Memoize dynamically compiled TypeScript security regexes in a sync.Map. Fix: clone detection built its document list via a closure side-effect and returned nil, so ScanTargetFiles' cache hit skipped it and dropped every quality.duplicate-code finding on any warm-cache scan. Route it through VisitTargetFiles (bypasses the findings cache) instead. Verified: go build/vet/gofmt clean, golangci-lint 0 issues, full suite passes with -race, cold/warm scans byte-identical, ~1.2x-1.7x faster (small-large repos). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
alxxjohn
added a commit
that referenced
this pull request
Jul 2, 2026
🤖 I have created a release *beep* *boop* --- ## [0.7.0](v0.6.1...v0.7.0) (2026-07-02) ### Features * **cli:** add What's New banner and task-grouped menu ([c1df999](c1df999)) * **cli:** What's New banner and task-grouped menu ([#21](#21)) ([45e56f7](45e56f7)) * execute checks-improvement plan tiers 1-6 ([733862f](733862f)) * **parsers:** tree-sitter TypeScript engine behind parsers.treesitter flag ([5d09161](5d09161)) ### Bug Fixes * **ci:** extract version from var Number in homebrew validation ([01d7a24](01d7a24)) * **ci:** extract version from var Number in homebrew validation ([#23](#23)) ([ec21f3b](ec21f3b)) * **version:** make Number a var so ldflags injection works ([6b1ccad](6b1ccad)) ### Performance Improvements * **scan:** parse/read files once, parallelize sections, scope cache ([d181a4f](d181a4f)) * **scan:** parse/read files once, parallelize sections, scope cache ([#24](#24)) ([c79d9ec](c79d9ec)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Cuts redundant work in the scan engine and fixes a latent clone-cache correctness bug. From a performance audit of the scan hot path.
fileCorpus(runner/support/corpus.go) memoizes the per-target walk, file reads, and Go AST parses.qualityanddesignnow reuse one AST viasupport.ParseGoSourceinstead of re-parsing the same file. Taint/graph parsers keep their cheaper parse modes and are left untouched.NumCPU-bounded worker pool with deterministic, position-indexed result ordering.ScanCacheandArtifactStoreare now mutex-guarded andOnSectionCompleteis serialized. Section-level (not file-level) parallelism was chosen deliberately: some evaluators mutate closure state and are only safe within a serial section.(LeftDoc, RightDoc)so the overlap merge scans only that file-pair's bucket; document paths are slash-normalized once instead of per comparator call.sync.Mapand reused across files.Bug fixed
Clone detection built its document list via a closure side-effect and returned
nil, butScanTargetFilesskips the evaluator on a cache hit — so allquality.duplicate-codefindings silently disappeared on any second scan with a warm cache (confirmed against the original code: cold=6 clones, warm=0). Fixed by routing clone doc-collection throughVisitTargetFiles, which bypasses the findings cache.Verification
go build/go vet/gofmtclean; golangci-lint: 0 issues (CI gate).-race— no data races in the new concurrent path.unbounded-goroutines-in-loopon the worker pool (true false positive — goroutines are semaphore-bounded) to keep the repo's own CI self-scan clean.Notes
Also updated
.claude/knowledge/architecture-boundaries.mdwith the pure-evaluator cache constraint, the new concurrency model, and the per-section fingerprint scheme.🤖 Generated with Claude Code