Skip to content

scripts: consolidate benchmarking into bench.py; record scan/hash & walker dead-ends - #102

Merged
martinus merged 1 commit into
masterfrom
bench-consolidate-py
Jul 23, 2026
Merged

scripts: consolidate benchmarking into bench.py; record scan/hash & walker dead-ends#102
martinus merged 1 commit into
masterfrom
bench-consolidate-py

Conversation

@martinus

Copy link
Copy Markdown
Owner

What

Replace the three overlapping bench-*.sh scripts with a single extensible Python harness, scripts/bench.py, and document two measured dead-ends so they aren't re-attempted.

scripts/bench.py — one benchmark harness

Subsumes bench-scan.sh (warm A/B scan-makespan), bench-scan-cold.sh (cold drop_caches variant) and bench-ram.sh (peak RSS). It:

  • generates reproducible trees (reusing scripts/demo/gen.py),
  • runs a matrix of binaries × io-threads × walk-threads × env-variants over declarative workload profiles,
  • cold (default, via the sudoers tee /proc/sys/vm/drop_caches) or --warm, interleaved across rounds with within-round shuffling,
  • reports median/mean/min/max wall + user + sys (+ --rss peak RSS).

Profiles live in a dict (realistic, mixed, bigfile, many, big, git) — future needs add a key, not a script. scripts/demo/* is untouched (that's the GIF, not benchmarking).

scripts/bench.py                                              # realistic, cold, 5 rounds
scripts/bench.py -p mixed --bin base=/tmp/old --bin new=./oans   # A/B two builds
scripts/bench.py -p git --walk-threads 4,8,16,32             # thread sweep
scripts/bench.py -p many --io-threads 2,4,8 --rss            # + peak RSS

DUPEREMOVE_WALK_THREADS — benchmark hook + a recorded dead-end

Overrides only the walker-thread count (decoupled from the csum/dedupe pools) so bench.py can sweep it. Measured conclusion: decoupling or doubling the walkers does nothing — they only feed the single __scan_file consumer, so past ~4 they're never the bottleneck; the csum pool (--io-threads) is. Cold sweeps (io-threads pinned at 8):

walkers ~/git median many median
4 14.35 s 8.33 s
8 14.48 s 8.01 s
16 14.52 s 7.88 s
32 14.58 s 8.01 s

Verified real (not a no-op): the same harness's io-threads control swept 1→2→8 = 38.0/20.7/7.9 s, DUPEREMOVE_WALK_THREADS=N produced exactly N live walker threads, and each run stored 250k extents. Default (unset) behavior is unchanged.

CLAUDE.md dead-ends

Also records that separating the walk from hashing into two sequential phases isn't worth it — cold-benchmarked as byte-identical output, neutral-to-~3%-worse (it throws away the walk/hash pipeline overlap).

Test

scripts/verify.sh passes: build (warnings = failure), 94 unit+integration tests, valgrind scan+dedupe+replay smoke.

🤖 Generated with Claude Code

…alker dead-ends

Replace the three overlapping bench-*.sh scripts with a single extensible
Python harness, scripts/bench.py, and document two measured dead-ends so they
are not re-attempted.

bench.py subsumes bench-scan.sh (warm A/B scan-makespan), bench-scan-cold.sh
(cold drop_caches variant) and bench-ram.sh (peak RSS): one tool that generates
reproducible trees (reusing scripts/demo/gen.py), runs a matrix of
binaries x io-threads x walk-threads x env-variants over declarative workload
profiles, cold or warm, interleaved across rounds, reporting
median/mean/min/max wall + user + sys (+ --rss peak RSS). Profiles live in a
dict (realistic/mixed/bigfile/many/big/git) so future needs add a key, not a
script. Cold runs now work via the sudoers `tee /proc/sys/vm/drop_caches`.
scripts/demo/* is untouched (that is the GIF, not benchmarking).

Add DUPEREMOVE_WALK_THREADS: a benchmark-only hook that overrides just the
walker-thread count (decoupled from the csum/dedupe pools) so bench.py can sweep
it. Measured conclusion (in CLAUDE.md): decoupling or doubling the walkers does
nothing — they only feed the single __scan_file consumer, so past ~4 they are
never the bottleneck; the csum pool (--io-threads) is. Default (unset) behavior
is unchanged.

CLAUDE.md also records that separating the walk from hashing into two
sequential phases is not worth it (cold-benchmarked: byte-identical output,
neutral-to-~3%-worse because it throws away walk/hash overlap).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@martinus
martinus merged commit ac92d97 into master Jul 23, 2026
4 checks passed
@martinus
martinus deleted the bench-consolidate-py branch July 23, 2026 05:05
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