docs/operations/hotpath-warp-abba-runbook.md
This runbook describes how to collect formal Linux or production-cluster evidence for hotpath performance changes. Use it when a short local A/B smoke run is too noisy to decide whether a regression is real.
The ABBA runner executes each workload and drive-sync cell as:
A1 baseline -> B1 candidate -> B2 candidate -> A2 baseline
B1 and B2 are compared with A1 to measure the candidate delta. A2 is
also compared with A1 to measure baseline drift. Treat a candidate regression
as actionable only when the A2 drift is passing or materially smaller than
the B1 and B2 delta for the same workload.
Use this runbook for hotpath profiling and performance validation of RustFS object I/O changes, especially when CPU, memory allocation, lock/channel wait time, request throughput, or tail latency is the review question.
The script validates the same workload matrix as the hotpath warp A/B gate:
| Workload | mode | size |
|---|---|---|
put-4kib | put | 4KiB |
put-4mib | put | 4MiB |
get-4kib | get | 4KiB |
get-4mib | get | 4MiB |
get-10mib | get | 10MiB |
mixed-256k | mixed | 256KiB |
Each workload runs with RUSTFS_DRIVE_SYNC_ENABLE=true and
RUSTFS_DRIVE_SYNC_ENABLE=false, so a full ABBA pass produces 48 measurement
cells: 6 workloads x 2 drive-sync modes x 4 ABBA legs.
Run the formal pass on Linux, not on a laptop smoke environment.
Required tools on the bench host:
bash, curl, git, and core GNU userland.warp on PATH, or pass --warp-bin.pidstat, mpstat, iostat,
sar, perf, heaptrack, or the platform's equivalent observability stack.Cluster-mode requirements:
RUSTFS_DRIVE_SYNC_ENABLE for the current ABBA leg.Build the baseline from the comparison commit, usually origin/main or the
previous accepted release:
git fetch origin main
git switch --detach origin/main
cargo build --release -p rustfs --bins
cp target/release/rustfs /tmp/rustfs-baseline
Build the candidate from the PR commit:
git switch <candidate-branch>
cargo build --release -p rustfs --bins
cp target/release/rustfs /tmp/rustfs-candidate
For cross-compiled cluster binaries, keep both outputs on the bench host and
make the deploy hook copy the selected binary to the cluster. The ABBA runner
passes the selected binary path through HOTPATH_ABBA_BINARY.
Use local mode for a dedicated Linux runner with disposable data paths. This is not a substitute for a production-like cluster, but it is useful before spending cluster time.
scripts/run_hotpath_warp_abba.sh \
--baseline-bin /tmp/rustfs-baseline \
--candidate-bin /tmp/rustfs-candidate \
--address 127.0.0.1:9000 \
--data-root /var/tmp/rustfs-hotpath-abba \
--disks 4 \
--duration 120s \
--rounds 3 \
--cooldown 30 \
--concurrency 16 \
--out-dir target/hotpath-abba/linux-local
The script starts and stops RustFS for each ABBA leg. The data root is throwaway and should not contain important data.
Use external mode when RustFS lifecycle is managed by ansible, systemd, a
cluster scheduler, or a dedicated deployment harness. In this mode the ABBA
script does not start RustFS directly; it calls --deploy-hook before each leg
and then waits for http://<endpoint><health-path>.
The deploy hook receives:
| Environment variable | Value |
|---|---|
HOTPATH_ABBA_LEG | A1, B1, B2, or A2 |
HOTPATH_ABBA_PHASE | baseline or candidate |
HOTPATH_ABBA_BINARY | selected baseline or candidate binary path |
HOTPATH_ABBA_DRIVE_SYNC | true or false |
Example ansible-shaped command:
scripts/run_hotpath_warp_abba.sh \
--baseline-bin /srv/rustfs-binaries/rustfs-baseline \
--candidate-bin /srv/rustfs-binaries/rustfs-candidate \
--endpoint rustfs-bench.example.internal:9000 \
--deploy-hook '
set -euo pipefail
cd /srv/rustfs-ansible
cp "${HOTPATH_ABBA_BINARY:?}" roles/rustfs/files/rustfs
export RUSTFS_DRIVE_SYNC_ENABLE="${HOTPATH_ABBA_DRIVE_SYNC:?}"
ansible-playbook -f 4 -l bench rustfs-manage.yml --tags stop
ansible-playbook -f 4 -l bench rustfs-manage.yml --tags config
ansible-playbook -f 4 -l bench rustfs-manage.yml --tags binary-copy
ansible-playbook -f 4 -l bench rustfs-manage.yml --tags start
' \
--duration 180s \
--rounds 5 \
--cooldown 45 \
--concurrency 32 \
--out-dir target/hotpath-abba/cluster-pr-XXXX
For formal evidence, prefer --rounds 5 or higher when the cluster budget
allows it. The script enforces --rounds >= 3.
ABBA warp output answers whether the candidate changed throughput or latency. Collect host telemetry at the same time to explain why.
Recommended minimum:
mkdir -p target/hotpath-abba/cluster-pr-XXXX/telemetry
pidstat -durh 5 > target/hotpath-abba/cluster-pr-XXXX/telemetry/pidstat.txt &
PIDSTAT_PID=$!
mpstat 5 > target/hotpath-abba/cluster-pr-XXXX/telemetry/mpstat.txt &
MPSTAT_PID=$!
iostat -xz 5 > target/hotpath-abba/cluster-pr-XXXX/telemetry/iostat.txt &
IOSTAT_PID=$!
Stop the collectors after the ABBA script exits:
kill "$PIDSTAT_PID" "$MPSTAT_PID" "$IOSTAT_PID"
For deeper CPU attribution, run perf record around one representative
workload after the ABBA gate identifies a candidate regression or improvement:
perf record -F 99 -g -- sleep 180
perf report --stdio > target/hotpath-abba/cluster-pr-XXXX/telemetry/perf-report.txt
For allocation profiling, build the candidate with:
cargo build --release -p rustfs --bins --features hotpath-alloc
Then run the same ABBA command with that binary. Compare allocation-heavy
function sections only within the same build mode. Do not compare
hotpath-alloc binaries directly with default release binaries for throughput
acceptance, because allocation instrumentation intentionally changes what is
measured.
For CPU hotpath sections emitted by hotpath, build with:
cargo build --release -p rustfs --bins --features hotpath-cpu
Use the CPU-enabled report to explain hotspots after the default or plain
hotpath ABBA gate shows a real effect.
The ABBA runner writes:
<out-dir>/
manifest.env
abba_schedule.csv
candidate_gate.md
baseline_drift_gate.md
summary.md
<workload>/<sync>/<leg>/median_summary.csv
<workload>/<sync>/<leg>/baseline_compare.csv
Attach or link at least these files in the issue or PR:
summary.mdcandidate_gate.mdbaseline_drift_gate.mdabba_schedule.csvmedian_summary.csv and baseline_compare.csv for a failed or
borderline workloadUse this decision table:
| Candidate gate | A2 drift gate | Interpretation |
|---|---|---|
| PASS | PASS | Candidate is acceptable for the measured matrix. |
| WARN | PASS | Candidate has a small measurable signal; inspect telemetry and decide if it is expected. |
| FAIL | PASS | Candidate likely regressed the affected workload; investigate before merge. |
| FAIL | FAIL on the same workload | Environment drift is high; rerun on a quieter runner or increase duration and rounds. |
| PASS | FAIL | Candidate did not exceed the budget, but the rig was unstable; avoid using the numbers as proof of improvement. |
When B1 and B2 disagree, treat the result as inconclusive even if the gate
passes. Increase duration, rounds, cooldown, or runner isolation before drawing
a conclusion.
When delegating the run to an AI agent or an automation runner, provide these inputs explicitly:
The AI agent should execute this sequence:
uname -a, RustFS commits, binary SHA256 sums, warp --version,
CPU model, memory size, disk layout, and whether the run is local or cluster.scripts/run_hotpath_warp_abba.sh --dry-run with the final arguments.--rounds >= 3.summary.md, candidate_gate.md, and baseline_drift_gate.md.Do not report a performance win or loss when the baseline drift gate failed on the same workload and no rerun was collected.