Improve scan performance#207
Merged
Merged
Conversation
|
🎯 Code Coverage (details) 🔗 Commit SHA: 817bf21 | Docs | Datadog PR Page | Give us feedback! |
whitemerch
force-pushed
the
chakib.hamie/scanner_race_fixes
branch
from
June 23, 2026 09:55
a374d80 to
018751d
Compare
whitemerch
force-pushed
the
chakib.hamie/scanner_race_fixes
branch
3 times, most recently
from
June 23, 2026 10:32
be618b1 to
d4509ed
Compare
whitemerch
marked this pull request as ready for review
June 23, 2026 10:39
whitemerch
force-pushed
the
chakib.hamie/scanner_race_fixes
branch
3 times, most recently
from
June 24, 2026 11:20
af9940d to
b36ef24
Compare
MarshalX
reviewed
Jun 24, 2026
MarshalX
left a comment
Contributor
There was a problem hiding this comment.
Great job! Awesome performance gains!
The rest is only about correctness of shared cache between scans, better control of memory consumption and cache hash collisions
whitemerch
force-pushed
the
chakib.hamie/scanner_race_fixes
branch
2 times, most recently
from
June 24, 2026 13:42
01b2ca0 to
b36ef24
Compare
MarshalX
reviewed
Jun 24, 2026
…runner buffer reuse, and license/format fixes.
whitemerch
force-pushed
the
chakib.hamie/scanner_race_fixes
branch
from
June 24, 2026 16:54
6a76c25 to
7d45da3
Compare
whitemerch
force-pushed
the
chakib.hamie/scanner_race_fixes
branch
from
June 24, 2026 17:00
7d45da3 to
817bf21
Compare
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.
TL;DR
All benchmarks below use
cloud-inventorywith-t Terraform(28,914 files).Peak RSS measured with
/usr/bin/time -l.The scan goes from 337 s on
mainto 46 s (with--x-parallelparsing) with all improvements stacked.The dominant individual win is a single change, the Terraform per-directory variable cache,
which alone cuts wall time from 134 s to 49 s (2.7×).
Wall Time
Results at a Glance
main(baseline)terraform.regofixPhase Breakdown (CPU time)
CPU time is aggregate across all goroutines; wall time for a phase can be shorter when work is parallelised.
prepare_sources: file parsing phasestart_scan: OPA rule evaluation phaseFull phase table (CPU seconds)
Memory Profile (peak RSS)
Measurements are peak resident set size from
/usr/bin/time -l.Memory is flat across all steps (~1.4–1.5 GB). The caches (dirVarsCache, HCL body cache)
trade CPU time for speed, not memory — the saved allocations are offset by retaining parsed
structures, leaving net RSS unchanged. The dominant cost is the OPA input data (one document
per Terraform resource) held in memory during
start_scan; that does not change across steps.Per-Optimization Analysis
01: Race fix +
--x-parallelparsingWall: 337 s → 137 s (−59%)
Parallel file parsing cuts wall time significantly by spreading the I/O and parse load across cores.
prepare_sourcesCPU increases (more total work due to thread overhead and contention), but walltime drops because the work runs concurrently across cores instead of serially.
The underlying race fixes are necessary prerequisites:
vulnerability_builder.go: removedSetupLogsshared-state write under concurrencydocker_detect.go: changed shallow slice alias to a deep copy preventing concurrent mutationsinspector.go: removed the decode-phase wall-clock deadline that was silently dropping findings02: OPA v1 + precomputed stores + pre-parsed Rego
Wall: 137 s → 134 s (−2%)
Wall time barely moves at this step because
prepare_sourcesstill dominates. The OPA changesprecompute one
inmem.Storeper platform from the merged input data once per scan (instead ofrebuilding it from JSON for every query), and pre-parse the 82 KB of shared Rego library text once
at startup via
rego.ParsedModule(). The benefit materialises instart_scanCPU time — itsets up the gains visible in later steps.
03: Terraform per-directory variable cache (
dirVarsCache)Wall: 134 s → 49 s (−63%)
The single biggest improvement in the suite.
Without the cache, every
.tffile in a directory triggersgetInputVariables+getDataSourcePolicy, which re-reads and re-parses all.tffiles in that directory tobuild the variable/locals/data-source map. In a large repository with many
files per directory, this is O(N²) re-parsing. The
dirVarsCache+singleflight.Groupreduces it to one parse per directory, shared (read-only cloned) by all files in that directory.
04: Module HCL body cache + parallel
parseHCLBodiesWall: 49 s → 48 s (−2%)
Two benefits:
parsedBodyCache sync.Map): the same.tfbytes are never lexed/parsed morethan once per process lifetime. In multi-phase scans (module discovery, then engine inspection)
this eliminates a full second pass over all files.
parseHCLBodiesnow dispatches parse work to a worker pool (GOMAXPROCSworkers), then merges in original file order for deterministic locals/variable shadowing.
05: Runner buffer pool +
terraform.regofixWall: 48 s → 46 s (−4%)
Two distinct sub-changes:
Runner buffer pool (
scanReadBufferPool sync.Pool): reuses the 1 MiB read buffers acrossfiles instead of allocating one per file. Reduces allocation pressure in
prepare_sources(CPU: 74 s → 28 s) and
start_scan(CPU: 46 s → 33 s).terraform.regofix (resolve_reference_name): changes the rule to collect all matchingcandidates into a set before selecting one, avoiding OPA's "multiple-output" error when the same
resource name appears across multiple module instances in separate documents. This is why
violations tick up from 696 to 700 — findings that were being silently suppressed by OPA
evaluation errors are now correctly reported (see Correctness section).
Correctness Check
All binaries produce the same exit code (60 = CRITICAL findings present) and scan the same
28,914 Terraform files (
-t Terraformoncloud-inventory).+4 violations, +1 rule (05 onwards): This is the
terraform.regofix forresolve_reference_name. Before the fix, OPA's multi-value rule evaluation silently failed whenthe same resource appeared across multiple module instance documents, suppressing findings. The
fix makes that function deterministic, surfacing 4 previously suppressed findings and making 1
additional rule produce results. This is a correctness improvement, not a regression.
Key Takeaways
~7.3× end-to-end speedup (337 s → 46 s with
--x-parallelparsing) overmainoncloud-inventory/-t Terraform.The terraform
dirVarsCacheis the most impactful single change: cuts wall time from134 s to 49 s (−63%). The root cause was O(N²) re-parsing of directory contents for every
file in that directory.
Memory footprint is flat (~1.4–1.5 GB RSS) across all steps. The caches trade CPU cycles
for speed without adding net memory.
No regressions. All scans complete, finding counts either match or increase for documented
correctness reasons, and no rules time out on any improved binary.
Author Checklist
I submit this contribution under the Apache-2.0 license.