fold/docs/internal/perf-audit/micro-benchmarks.md
2026-05-27 10:36:57 -04:00

3.5 KiB

Optimization micro-benchmarks

bench/run_micro_opt.py is the synthetic A/B harness for the current speed and false-positive reduction backlog. It generates tiny C++ projects, runs fold scan --profile, and writes per-case SARIF/profile artifacts plus summary.json and summary.md.

Use it before and after each optimization patch:

python3 bench/run_micro_opt.py --case all --repeats 3
# compare medians in bench/results/<timestamp>_micro-opt/summary.json

For quick smoke while iterating:

python3 bench/run_micro_opt.py --case all --size 4 --repeats 1 --out-dir /tmp/fold-micro-smoke

Cases

Case Optimization validated Main metrics to compare Invariant
branch-merge SecurityWalker::walkIf / SymbolicEnv dirty-binding or cheaper branch join logic null-deref.wall_ms, states_merged, states_kept_separate, serial_dispatch_ms finding count and confidence distribution stay stable
defuse-null direct DefUseChains lookup by (var, use_loc) in NullDerefObserver::shouldQuery null-deref.wall_ms, z3_queries, external elapsed finding count stays stable
cross-tu-prime skipping/deduplicating redundant per-TU cross-TU priming after global priming serial_dispatch_ms, total_wall_ms, findings by rule cross-TU callsite findings stay stable
precision-fp shared precision evidence / confidence demotion for imprecise security findings by_confidence, detector finding counts exact findings stay; imprecise findings move from proved to heuristic where appropriate
expr-cache query-hash/cache changes, especially avoiding expensive canonical string hashing detector wall_ms, z3_queries, z3_timeouts findings and confidence distribution stay stable
curl-str-bound Curl-style bounded parser output (curlx_str_*) feeding curlx_strlen(&out) into a stack buffer terminator index oob.findings_emitted, oob.wall_ms, z3_queries max+1 buffer terminator writes produce 0 findings while undersized-buffer unit tests still flag

Suggested acceptance gates

Do not use absolute milliseconds as hard gates across machines. Prefer comparing a before/after run on the same machine/build:

  • Performance patches: median target metric should improve by at least 10% on the relevant case, with no new findings and no lost findings unless the patch is explicitly an FP reduction.
  • FP/confidence patches: total findings may stay the same, but confidence distribution should move in the intended direction; exact/proved positives in the smoke cases must not disappear.
  • Profile/instrumentation patches: new metrics should appear in profile JSON, and existing metrics should remain populated.

Each repeat writes raw artifacts:

<case>-<size>-r<N>.sarif
<case>-<size>-r<N>.profile.json
<case>-<size>-r<N>.stdout.log
<case>-<size>-r<N>.stderr.log

Use --keep-workdir when you want to inspect generated source and compile DBs.

Real-code presets

bench/run_security_targets.py runs the current source-security presets:

python3 bench/run_security_targets.py --preset yams-wide20-security --repeats 3
python3 bench/run_security_targets.py --preset all --repeats 1

Presets skip themselves when the local compile database is missing. Use yams-wide20-security as the quick real-code gate, then yams-full-security and curl-security for slower validation.

Added case: control-nesting

control-nesting stresses nested branches/loops and should be used for changes that target control_walk_ms, sink prechecks, or branch pruning counters.