Verification
Every figure in Starf was checked against either a known load or another tool before being trusted. This records what was checked and what came back, so the claims can be re-run rather than taken on faith.
The machine throughout is an M4 Max — 16 logical processors, 12 performance and 4 efficiency, 128 GB — running about 1,250 processes.
Process CPU, against ps
Two yes processes were started, each of which pins one processor:
PID CPU% NAME
15441 100.0 yes
15442 100.0 yes
ps: 15441 99.1 15442 98.9
Exactly 100.0% each on the per-processor scale, against ps's 99.1 and 98.9.
Host CPU, against the processor count and top
CPU user 419.26% system 146.25% idle 1034.49% (of 1600% capacity)
user + system + idle = 1600.00%, which is exactly 16 processors. A separate run under load
gave system 21.5% where top, sampled a moment later, gave 21.92%.
Per-processor rates, against the host total
With four spinners running, the mean across the sixteen processors was 47.92%, against the host's (227.17 + 504.49) / 1600 = 45.7% measured a moment later. The spinners spread across processors rather than pinning four — threads migrate, and the aggregate is what has to agree.
Performance and efficiency identification, against sysctl
CPU 0–3 Efficiency hw.perflevel1.physicalcpu = 4
CPU 4–15 Performance hw.perflevel0.physicalcpu = 12
The kinds come from cluster-type on the IODeviceTree nodes; the counts come from
sysctl. They agree.
GPU, against a known Metal load
scripts/gpu-load.swift was run for ten seconds while sampling:
Apple M4 Max (40 cores)
Device 99%
Renderer 45%
Tiler 23%
PID GPU % NAME
46272 52.71 gpu-load
399 22.34 WindowServer
4949 15.60 com.apple.WebKit.GPU
2425 3.58 iTerm
44693 1.88 xpress
1551 1.83 eterm
The per-process percentages sum to 99.9% against the device's 99%. Agreement to under a percent between two independently reported counters is the strongest check available without Apple's own code to compare against.
Idle, the device reads 0% while processes still report a few percent between them: the device figure is instantaneous and the process figures cover the sampled second.
Subtree totals, against an independent implementation
scripts/verify-subtrees.py is a second implementation, not a refactor of the first. It
rebuilds the forest from the raw records — re-applying the missing-parent, reused-PID and
cycle rules — and recomputes every total with Python's exact integers and its own float
arithmetic:
$ cargo run -q --manifest-path src-tauri/Cargo.toml --example dump -- json \
| python3 scripts/verify-subtrees.py
1249 processes, 68 with descendants, 1181 leaves
680 subtree totals recomputed independently
all totals match
The counts move with whatever the machine is running — a later run checked 810 totals across 1,292 processes — but "all totals match" is the part that has to hold every time.
Per-thread rates, against the process figure
A single-threaded yes process:
THREAD TOTAL SYSTEM NAME
Thread 8836719 98.65% 84.79% Unnamed thread
against the same process reading ~100% at process level. Starf's own 25 threads read as
named tokio-rt-worker entries summing to 4.08%.
Open files, against lsof
On a Finder process:
starf: 11 descriptors
lsof: 11 rows with a numeric file descriptor
(154 rows in total, the rest being the working directory and mapped files,
which are not descriptors)
Memory map, against vmmap and the kernel
The same Finder process:
starf: 1,326 mappings, 446.49 GB virtual
kernel: pti_virtual_size = 446,488 MB
vmmap: TOTAL, minus reserved VM space 3.2G
The gap is reserved address space, and the three largest mappings account for it:
0x0000001000000000 412.32 GB prot 0 share 3 (SM_EMPTY)
0x00000006c0000000 12.79 GB prot 0 share 3
0x00000009c6800000 12.78 GB prot 0 share 3
No access, no backing: address space held but never mapped, which is exactly what vmmap
excludes from its headline. Starf's total agrees with the kernel's own; the memory map
reports reserved space separately rather than letting it quietly inflate a figure, and the
address-range plot leaves those mappings at their true size.
Region counts differ from vmmap because PROC_PIDREGIONPATHINFO coalesces adjacent
mappings with identical attributes and vmmap splits differently.
Per-process network, against nettop
starf nettop
512 mDNSResponder 4814287392 mDNSResponder.512 4814287392
20801 netbiosd 44824669 netbiosd.20801 44824669
2648 Google Chrome H… 23456042 Google Chrome H.2648 23456042
Exact, for the counters that had not moved between the two runs.
Battery, against pmset and System Settings
Charge 80% matches pmset -g batt
Cycle count 186 matches System Settings
Charge / max / design 3881 / 5120 / 6249 mAh
Adapter rating 90 W matches pmset -g ac
Time to empty — the controller reported 65535, its "no estimate" sentinel
Application classification
30 of 1,249 processes classified as applications. Three were checked by hand because they
looked wrong — AppSSOAgent, UserNotificationCenter, privatecloudcomputed — and each
genuinely declares neither LSUIElement nor LSBackgroundOnly. They set their policy at
runtime, which no static read can see. This is recorded as a known inaccuracy rather than
patched over with a path rule.
Automated tests
cargo test --manifest-path src-tauri/Cargo.toml 76 tests
pnpm test 19 tests
The Rust tests cover the rate rules (first sample, denied counter, reset counter, 32-bit tick wrap), the tree rules (missing parent, reused PID, cycle broken at the smallest PID, a 50,000-deep chain, partial and unavailable totals, exact-integer overflow), the GPU tracker (changed counter arrays, one counter falling while the sum grows, observed against lifetime time), per-processor rates, per-thread rates, the history budget, the battery's signed current and sentinel, and application path classification.
The interface tests cover forest building, ancestor context, collapse keyed by identity, and the export semantics — an unavailable counter as an empty cell, a measured zero as zero, quote escaping, and subtree completeness.
Two of those tests found real bugs while being written:
- The frontend added an ancestor PID with no row of its own to the included set, so its children joined a branch that was never drawn and disappeared from tree mode.
- The first battery tests asserted arithmetic written inside the test rather than the code's. They were rewritten against the real functions, which meant extracting the pure parts so they could be called.