Repository navigation
iOS warm snapshot daemon cost is about double the #2189 baseline #2751
Description
What
Warm interactiveOnly snapshots of iOS Simulators cost about twice the daemon time they cost at
71fb2483f3 (the #2189 baseline corpus head). Found while interpreting the final convergence corpus
in #2750; recorded in docs/evidence/ios-snapshot-convergence-final-2026-09-21.md.
The published warm cells show it (daemon medians 89–202 ms against the baseline's 50–209 ms), and it
survives a controlled side-by-side, so it is not target, runtime, app, or load: same Simulator
(bench-2188-final, iOS 26.2), same installed fixture app, same ambient load (1-minute average ~21),
back-to-back runs of ten warm snapshots of the smallest fixture (4 nodes, ~3.4 KB), reading the
daemon's own per-step duration.
| CLI under test | Durations (ms) | Median |
|---|---|---|
71fb2483f3 |
68, 47, 46, 44, 43, 43, 43, 45, 47, 46 | 45.5 |
7c434b5758, round 1 |
97, 86, 84, 90, 84, 86, 86, 92, 83, 82 | 86 |
7c434b5758, round 2 |
98, 133, 96, 96, 88, 90, 87, 94, 107, 103 | 96 |
A repeat at a 1-minute load average of 3.8 still measured 86 ms. The shape is a roughly fixed ~40 ms
per snapshot, not work proportional to tree size.
Where to look
Candidates in 71fb2483f3..7c434b5758 that add work to every capture-consuming command:
- fix(ios): Simulator AX bridge reports enabled from the NotEnabled trait #2644 — Simulator AX bridge reports enabled from the
NotEnabledtrait (per-node trait reads). - feat(ios): publish the captured keyboard band as a producer-declared fact #2670 — publish the captured keyboard band as a producer-declared fact.
- feat(#2682): disclose the target re-activation on every capture-consuming command #2693 — disclose the target re-activation on every capture-consuming command.
- refactor(ios-runner): acquire first, present after — one geometry normalization pass instead of per-walker threading #2661 — derive snapshot geometry in one pass after acquisition.
Reproduce
UDID=<simulator with com.callstack.agentdevicelab installed>
STEPS=$(python3 -c "import json;print(json.dumps([{'command':'snapshot','input':{'interactiveOnly':True}}]*10))")
node bin/agent-device.mjs open com.callstack.agentdevicelab --launch-url 'agent-device-test-app://inert' \
--foreground --udid "$UDID" --session probe --state-dir .tmp/probe-state --json >/dev/null
node bin/agent-device.mjs batch --steps "$STEPS" --udid "$UDID" --session probe \
--state-dir .tmp/probe-state --json | python3 -c "
import json,sys,statistics; d=json.load(sys.stdin)
print([r['durationMs'] for r in d['data']['results']], statistics.median(r['durationMs'] for r in d['data']['results']))"
node bin/agent-device.mjs close --udid "$UDID" --session probe --state-dir .tmp/probe-state --json >/dev/nullRun it from both checkouts back to back (the runner reinstalls per checkout, so each leg measures its
own build) and bisect with the same probe.
Why it matters
It does not weaken the convergence claims: one snapshot path, no presentation branching in the
assembly, cold-cold wall medians down 57–68%, and RTT sensitivity down roughly fourfold in the proxy
matrix. It does mean warm observation is more expensive than the published baseline, and no one has
yet named the commit that made it so.
Activity