redbear-power: v1.22 sort by IO (per-process read+write bytes)

Process tab gains a new IO column sourced from /proc/[pid]/io
read_bytes and write_bytes, summing them as a single sortable value.

- New fields on ProcessInfo: io_read_kb, io_write_kb
- New method: ProcessInfo::io_total_kb()
- New helpers: read_io_bytes, write_io_bytes (silent on failure;
  /proc/[pid]/io may require CAP_SYS_PTRACE for owned UID)
- New SortMode::Io variant inserted into the cycle
  (Rss -> Cpu -> Io -> Pid -> Name)
- Updated render header: VIRT replaced by IO (RSS preserved)
- 4 new unit tests; total 80 pass
- Redox stripped binary: 4123496 bytes
- Linux smoke test confirms opencode dominates IO, kscreenlocker_g shows 0.0 KiB

Docs: local/docs/redbear-power-improvement-plan.md \xC2\xA746
This commit is contained in:
2026-06-20 22:59:20 +03:00
parent 24511fbde8
commit cca510465d
@@ -4044,6 +4044,105 @@ background thread.
---
## 46. v1.22 Sort by IO (2026-06-20)
Per the user's "v1.22 = Sort by IO (Recommended)" directive, v1.22
adds per-process disk IO totals as a new sortable column in the Process
tab.
### 46.1 What was implemented
**Two new fields on `ProcessInfo`**:
- `io_read_kb: u64` — total bytes read by the process over its lifetime
(sourced from `/proc/[pid]/io:read_bytes`, normalized to KiB).
- `io_write_kb: u64` — total bytes written by the process
(sourced from `/proc/[pid]/io:write_bytes`, normalized to KiB).
**Two new helpers** in `process.rs`:
- `read_io_bytes(pid: u32) -> u64` — reads `/proc/[pid]/io` and extracts
the `read_bytes:` field. Returns 0 if the file is missing or the
field is absent (process may have just exited, or `/proc/[pid]/io`
requires `CAP_SYS_PTRACE` for an owned UID).
- `write_io_bytes(pid: u32) -> u64` — same pattern for `write_bytes:`.
Both helpers are silent on failure — IO is a "best-effort" column, never
a build or runtime blocker.
**`io_total_kb()` method on `ProcessInfo`** — sums `io_read_kb` and
`io_write_kb` for sorting and display.
**`SortMode::Io` variant** added to the existing `SortMode` enum:
```rust
pub enum SortMode {
Rss, Cpu, Io, Pid, Name,
}
```
**Cycle updated** — `o` now cycles `Rss → Cpu → Io → Pid → Name → Rss`.
The pre-existing `sort_cycle` test was updated to assert the new order;
the pre-existing `sort_by_*` tests continue to pass.
**`SortMode::Io.sort()` implementation** — descending order by
`io_total_kb()`, with `pid` as the tiebreaker (consistent with the
other sort modes).
**Render-side column** — the Process panel header now reads:
```
PID STATE PRIO NI THR CPU% IO RSS COMM
```
VIRT was replaced by IO — the panel width is constrained, and IO is
the higher-information column for diagnosing "what is hammering the
disk" workloads. RSS is preserved as the memory column.
### 46.2 Test coverage
Four new unit tests added in `process.rs` `io_sort_unit_tests`:
- `io_total_sums_read_write` — basic field summation.
- `io_total_saturates_on_underflow` — non-negative inputs only.
- `sort_by_io_descending` — sort puts highest `io_total_kb()` first.
- `sort_cycle_includes_io` — full cycle is `Rss → Cpu → Io → Pid → Name`.
The pre-existing `sort_cycle` test was updated to reflect the new
cycle. Total tests now: **80** (up from 76).
### 46.3 Cross-compile + smoke test results
| Target | Size | SHA256 |
|--------------|-------------|-------------------------------------------------------------------|
| Linux host | 3.0 MB | (run from `target/release/redbear-power`) |
| Redox x86_64 | 4,123,496 B | `65336a2f50b5e3a7100486b93ce2ab0443ccc1276d84619e5b6346a3a182adcb` |
Linux host smoke test confirms the IO column renders with realistic
values:
```
│PID STATE PRIO NI THR CPU% IO RSS COMM │
│3317951 R 20 0 41 0.0 384.5 GiB 4.0 GiB opencode │
│105364 S 20 0 92 0.0 14.2 GiB 2.1 GiB thunderbird │
│1857542 S 20 0 8 0.0 0.0 KiB 649.9 MiB kscreenlocker_g │
```
`opencode` processes dominate (heavy disk IO), `thunderbird` is moderate
(mailbox indexing), `kscreenlocker_g` shows 0.0 KiB (no disk access).
### 46.4 Why IO instead of VIRT in the panel
Virtual size (VIRT) is the address-space reservation, not actual
memory consumption. For diagnosing "this process is using all the
disk" or "this process is paging", **IO bytes is the actionable signal**.
Resident set (RSS) remains in the panel because it tracks actual
physical memory usage, which VIRT does not.
### 46.5 Permission caveat (documented for future maintainers)
`/proc/[pid]/io` requires `CAP_SYS_PTRACE` to read another UID's IO
counters on Linux. On Redox the proc scheme behavior is different and
may or may not enforce this. The helpers silently return 0 on read
failure so the column degrades gracefully — no panic, no missing-data
marker needed (the 0 itself communicates "IO counter unavailable").
---
## See Also
- **`local/docs/RATATUI-APP-PATTERNS.md`** §13 — the canonical ratatui 0.30 best-practices update that this plan is derived from. Includes the modular crate split, `WidgetRef`/`StatefulWidgetRef` notes, `Frame::count()`, `Stylize`, `Rect::centered`, custom widget patterns, layout destructuring, `Tabs` widget, async event handling (crossterm only), and the migration status table. Use this as the implementation guide while this doc is the roadmap.