Skip to content

fix: skip the redundant simulator list after a boot this run performed - #272

Merged
janicduplessis merged 1 commit into
mainfrom
fix/skip-redundant-sim-list
Sep 3, 2026
Merged

fix: skip the redundant simulator list after a boot this run performed#272
janicduplessis merged 1 commit into
mainfrom
fix/skip-redundant-sim-list

Conversation

@janicduplessis

@janicduplessis janicduplessis commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

Description

On a run that creates a simulator, ensureOwnedIosDevice boots it with a blocking simctl bootstatus -b and then ensureIosBooted opens with resolveOwnedIosSim(udid) -> listAllIosSims() -> xcrun simctl list devices --json, purely to learn a state it already knows. The sim is Booted, so the function returns on the next line -- but that list is the first simctl call after a boot, and CoreSimulator is still busy for several seconds after bootstatus claims the boot is done. Measured on this machine: simctl list devices --json costs 7.9 s right after a boot versus 0.06 s on a quiet one, and the device ... booted phase line reported 12.3 s / 8.7 s / 2.0 s across the three cache-hit baselines in investigations/2026-09-02-cache-hit-run-time.md (mean total 72.6 s).

Ownership is not weakened: ensureOwnedIosDevice already re-resolved the sim by name (resolveOwnedIosSim, or createOwnedIosSim for one it just made) earlier in the same call chain, so invariant 2 is satisfied before anything boots.

Solution

ensureOwnedIosDevice now reports the udid it booted on the record it returns (bootedUdid), and ensureIosBooted returns { ok: true, udid } immediately when that udid is the one it was asked about. It is deliberately narrow: the field is set only where this call actually ran bootIosSim -- the created path and the reuse path that found the sim shut down. A reused sim that was already Booted carries no bootedUdid, so it is still listed, because nothing in this process proves it did not shut down in between. A bootedUdid for a different sim does not vouch for this one either.

bootedUdid is attached after configureOwnedIosSim has written the registry, alongside created/deviceType/runtime, so it is never persisted -- it means "this process booted it", and it would be a lie in the next one.

I used the udid rather than the whole IosSimRecord the issue suggests: on the created path there is no IosSimRecord to return (createOwnedIosSim returns a name and a udid, not a simctl list row), and the udid match is the entire decision.

No tool call changes, so invariant 9 needs nothing new here; the argument lists are untouched and one simctl list devices --json is simply not issued.

Test plan

  • engine-device.test.ts: ensureBooted issues zero commands when the record carries a matching bootedUdid; it still lists for a reused sim with no bootedUdid, and for a bootedUdid that names another sim. ensureOwnedDevice reports the boot it performed on the created path and on the reuse-after-shutdown path, reports nothing on the already-booted path, and the persisted registry record is unchanged ({ deviceUdid, owned, deviceName }).
  • ios-command.test.ts: an end-to-end run wired to the real ensureBooted with a fake clock that charges 8 s per simctl list devices -- the phase line reads booted (0ms) on the fresh-boot path and booted (8s) on the path that has to list. Ablation: dropping the new early return in ensureIosBooted fails both this test and the engine one.
  • pnpm run format:check, lint, build, typecheck, pnpm test (83 files, 3336 tests), pnpm run knip all pass on this branch.

Fixes #268

@janicduplessis
janicduplessis force-pushed the fix/skip-redundant-sim-list branch from 5a06635 to 816c135 Compare September 3, 2026 06:24
@janicduplessis
janicduplessis merged commit e66bde6 into main Sep 3, 2026
5 checks passed
@janicduplessis
janicduplessis deleted the fix/skip-redundant-sim-list branch September 3, 2026 06:44
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.

A cache-hit iOS run re-lists simulators right after its own boot, costing 8 s

1 participant