Skip to content

benchmarks: count a stacked block device once in the container io figures (#555) - #570

Merged
tae898 merged 2 commits into
mainfrom
fix/io-stat-stacked-devices
Nov 6, 2026
Merged

tae898 merged 2 commits into
mainfrom
fix/io-stat-stacked-devices

Conversation

@tae898

@tae898 tae898 commented Nov 6, 2026 •

Copy link
Copy Markdown

Refs #555. The io part of the issue. This PR merges SECOND, after #571.

The bug: runner.read_io_stat and memory_probe.parse_io_stat summed every device line of a container's cgroup v2 io.stat. On the mini the file lists 259:0 (NVMe) and 252:0 (a device-mapper device stacked on it) with identical bytes, plus an unrelated 8:0 with 0 bytes, so every figure derived from it was recorded at about twice its value.

The fix: a listed device is skipped when it is a slave (directly or through further layers, partitions resolved to their whole disk) of another listed device, per /sys/dev/block/<maj:min>/slaves. The top of the stack is kept, unrelated disks still add up, and a device with no sysfs entry is counted as before. The sysfs root is injectable for tests. The first commit is 6c9c58b from the four-arm branch (#554), cherry-picked onto current main without conflicts.

The stamp: the runner now writes io_stat_dedup: 1 into every row, in the one row literal it builds (next to instrument; every io_* field of a row is written by this runner). A row carrying it counts a stacked device once, so the freeze can tell a fixed row from a pre-fix one without a cutoff time. #571 reads the stamp, halves the io figures of mini rows that lack it in the frozen copy only, and declares the column to page_check (NOT_PRINTED) and provenance_check (schema homogeneity, so a cell whose reps straddle the fix still passes). That is why #571 must merge first: with this PR on main and #571 not, the next freeze would fail page_check on the unknown column.

What changes: read_io_stat in runner.py delegates to parse_io_stat, parse_io_stat in memory_probe.py gets the stacked-device rule, and the runner row gets one added key. This does change the runner path, but only by that key and the dedup function; the stage scripts are unaffected until the mini pulls main after the merge. Apart from the new stamp, the only row fields whose values change are the io_* ones (io_read_mib, io_write_mib, the _sum pair, the per-side {client,server,server_container,sidecar_*}_io_* fields and the memory probe's io_<phase>_{read,write}_mib). I read the diff for that: the runner.py hunks are the one function and the one key, and the memory_probe.py hunk is the one function plus its helpers. The return keys (rbytes, wbytes) are unchanged. One behaviour difference outside the rule: a malformed token in io.stat is now skipped instead of making read_io_stat return {}.

Tests: seven tests for the dedup rule and one for the stamp in test_memory_probe.py (stacked pair counted once, two-layer stack, unrelated third device still counted, no sysfs info counts every device, bad input, the runner delegating to the same rule, the stamp placed in the row literal before any io field is written). I called the functions directly and they pass; CI runs them on this PR. compile(), pyflakes (no new warnings over main) and the repo's pre-commit hooks on the changed files are clean.

Merge is held on purpose, on two conditions that must both be true. First, #571 is merged. Second, the mini pass has finished the qC22 and qC23 re-runs, so the pass splits cleanly into rows before and after the fix (the stage scripts pull main at every stage start). Merge condition, one line: #571 is merged AND ssh mini 'grep -c "REORDER reruns finished" ~/STATUS.txt' prints 1 or more. Not ready for review until then.

🤖 Generated with Claude Code

…ures (#555)

cgroup v2 io.stat charges a write to a device-mapper device on it AND on the
disk under it. read_io_stat and parse_io_stat summed every line, so the io_*
fields were 2x on the mini (259:0 NVMe + 252:0 dm, identical wbytes).

A listed device is now skipped when it is a slave (transitively, partitions
resolved to whole disks) of another listed device per /sys/dev/block/*/slaves;
the top of the stack is kept, unrelated disks still add up, and a device with
no sysfs entry is counted as before. sysfs root is injectable for tests. Return
keys are unchanged and no row field is added.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…#555)

The stamp says the row's io figures count a stacked block device once, so the freeze (the companion
PR, which declares the column to page_check and provenance_check and merges first) tells a fixed
row from a pre-fix one without a cutoff time. One key in the one row literal the runner builds.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@tae898
tae898 marked this pull request as ready for review November 6, 2026 09:30
@tae898
tae898 merged commit 4272386 into main Nov 6, 2026
4 checks passed
@tae898
tae898 deleted the fix/io-stat-stacked-devices branch November 6, 2026 09:32
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