Skip to content

Memory screen: track the NE's disk writes against the daily budget - #240

Merged
torlando-tech merged 7 commits into
mainfrom
feat/ne-disk-writes-chart
Oct 27, 2026
Merged

torlando-tech merged 7 commits into
mainfrom
feat/ne-disk-writes-chart

Conversation

@torlando-tech

Copy link
Copy Markdown
Owner

Problem

The iPhone 14 *.diskwrites_resource .ips reports (limit of 12,137 KB over 86,400 s) are what get the background transport throttled and killed — and the Memory Usage screen had no way to show disk writes, because the NE memory trace carried no disk counter.

Change

  • Trace layout v2 (record 64 → 72 B): every record now carries the cumulative proc_pid_rusage → ri_diskio_byteswritten at sample time, sampled by the existing 1 Hz loop alongside the footprint. Boot/stop markers carry it too, so kill cards can show a dead generation's total.
    • proc_pid_rusage is not declared in the iOS SDK headers (libproc.h is macOS-only); resolved once via dlsym(RTLD_DEFAULT, …) — reading your own rusage needs no entitlement.
    • ensureFile now drops and recreates a file whose size does not match this build's layout (a v1 ring from an older build) instead of interleaving two geometries. The trace is diagnostics, not state — no migration.
  • Analyzer: per-point write rates (delta between consecutive plotted records within a generation — no live/bucket double counting) and per-event disk totals (last − first of the cumulative counter; nil for pre-v2 rings).
  • Screen: new "Disk writes" card — cumulative MB per process run with the ~11.9 MB/day budget dashed line (12,137 KB from the .ips reports), plus a disk total line on the kill card.

Testing

  • NEMemoryTraceTests: 24/24 on the Mac sim (layout round-trip incl. the new field, v1-file drop+recreate, kill disk total + per-point rate, counter reset across generations).
  • Full ColumbaAppTests suite running; device verification of the v2 ring + chart pending a device build.

The iPhone 14 .ips reports that get the NE throttled/killed are
diskwrites_resource breaches - 'limit of 12,137 KB over 86400 s' - which the
memory chart could not show because the trace had no disk counter.

Trace layout v2 (+8 B record): each record now carries the cumulative
proc_pid_rusage ri_diskio_byteswritten at sample time, sampled alongside the
footprint by the same 1 Hz loop and included on boot/stop markers so kill
cards show the dead generation's total. proc_pid_rusage is not declared in
the iOS SDK headers; resolve it via dlsym(RTLD_DEFAULT) - reading your own
rusage needs no entitlement. ensureFile now drops a file whose size does not
match this build's layout (a v1 ring from an older build) instead of
interleaving two geometries.

Analyzer derives per-point write rates (delta between consecutive plotted
records within a generation - no live/bucket double counting) and per-event
disk totals; the screen gains a cumulative-writes chart with the 11.9 MB/day
budget line.
@greptile-apps

greptile-apps Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] The change since the previous review appears safe to merge.

Summary

The PR adds disk-write counters to the Network Extension’s memory trace and shows write rates against the daily budget.

  • The shared trace records disk writes for each Network Extension run.
  • The Memory Usage screen shows disk-write rates and run totals.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[Network Extension samples disk writes] --> B[Trace layout v2]
  B --> C[Analyzer computes rates and totals]
  C --> D[Memory screen shows disk writes]
Loading

Reviews (7) · Last reviewed commit: "DiskIO: Darwin's RTLD_DEFAULT is (void*)..." · Reviewed by Greptile

Comment thread Sources/Shared/NEMemoryTrace.swift Resolved
@torlando-tech

Copy link
Copy Markdown
Owner Author

@greptile review

Greptile 5/5 review surfaced three real defects, all fixed:

- Kill-card disk total: the counter is cumulative since process start, so
  the total is the LAST reading outright. The previous last-minus-first
  subtraction dropped a run's early writes once the ring overwrote its boot
  marker (>5.6 days).
- A failed rusage probe now stores the diskWrittenUnavailable sentinel, never
  0 - a zero between real readings would fake a counter reset and inflate the
  next interval's rate. The analyzer renders it as no data and does not bridge
  the gap.
- The disk card plots the write RATE (KB/s) against the daily budget expressed
  as a rate (~0.14 KB/s) instead of cumulative-vs-fixed-line: a healthy
  multi-day run crossed a fixed daily line and read as a breach.
@torlando-tech

Copy link
Copy Markdown
Owner Author

All three P2s fixed in f04979e (+ chart nil-rate skip):

  1. Run totals lose older writes — the counter is cumulative since process start, so the kill total is now the LAST reading outright; the last − first subtraction is gone, which also removes the ring-wrapped undercount. Regression test testWrappedRingDoesNotDropEarlyWritesFromTheKillTotal pins the 19 MB early-writes case.
  2. Failed samples look like zero — a failed probe now stores the diskWrittenUnavailable sentinel (never 0); the analyzer renders it as no data, gives that point and the next no rate, and a generation ending on it reports no total. testFailedProbeIsNoDataRatherThanZero.
  3. Healthy runs look over budget — the card now plots the write rate (KB/s, 60 s-window averages) against the daily budget as a rate (~0.14 KB/s); bursts above it read as bursts, not breaches.

NEMemoryTraceTests 26/26 on the Mac sim.

@torlando-tech

Copy link
Copy Markdown
Owner Author

@greptile review

The first on-device run stored the sentinel on every record: the probe fails
on the real device while succeeding on the sim. Diagnose which leg fails
(symbol lookup vs syscall result + errno) with a single ext-diag.log line.
Comment thread Sources/Shared/NEMemoryTrace.swift Resolved
dlsym(NULL, …) fails on iOS (NULL is not RTLD_DEFAULT there — that is a
glibc-ism), which is why the first on-device run stored the sentinel on every
record while the sim worked. Pass RTLD_DEFAULT properly.
@torlando-tech
torlando-tech merged commit 92e3081 into main Oct 27, 2026
3 checks passed
@torlando-tech
torlando-tech deleted the feat/ne-disk-writes-chart branch October 27, 2026 02:09
@torlando-tech

Copy link
Copy Markdown
Owner Author

@greptile review

@torlando-tech

Copy link
Copy Markdown
Owner Author

Fixed: the once-only log is now guarded by a dedicated NSLock (check-and-set inside, log call outside).

@torlando-tech

Copy link
Copy Markdown
Owner Author

@greptile review

1 similar comment
@torlando-tech

Copy link
Copy Markdown
Owner Author

@greptile review

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