perf: speed up iOS replay runner#557
Conversation
ecba590 to
955a1f8
Compare
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ecba5906b8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| while (Date.now() - startedAt < timeoutMs) { | ||
| const result = await queryDirectIosSelector(params, params.session!, selector); | ||
| if (result?.found) { | ||
| const payload = { | ||
| kind: 'selector', | ||
| selector: selector.raw, | ||
| waitedMs: Date.now() - startedAt, | ||
| selectorChain: [selector.raw], | ||
| directSelector: true, | ||
| }; | ||
| recordIfSession(params.sessionStore, params.sessionName, params.req, payload); | ||
| return payload; | ||
| } | ||
| await sleep(DIRECT_WAIT_POLL_INTERVAL_MS); | ||
| } | ||
| throw new AppError('COMMAND_FAILED', `wait timed out for selector: ${selector.raw}`); |
There was a problem hiding this comment.
Fall back when direct iOS wait cannot resolve
For iOS simple selectors this direct path now owns the whole wait loop, but queryDirectIosSelector returns null on runner errors/ambiguous matches and found: false for matches the runner filters out as non-hittable; in both cases this loop keeps polling until it throws instead of falling back to the snapshot selector runtime. That regresses cases the existing waitForSelector path supports, such as a selector that matches multiple nodes or a visible non-hittable/container node, because findSelectorChainMatch only needs at least one snapshot match while the runner-side findElement requires a unique hittable element.
Useful? React with 👍 / 👎.
6326daf to
c68fd4c
Compare
c68fd4c to
33a7f5e
Compare
Summary
Speeds up the iOS replay runner while keeping the reliability fixes that fell out of the Maestro comparison.
High-level changes that moved the needle:
pnpm build:xcuitestleaves the runtime cache in the fast-path state instead of forcing one follow-up scan.id,label,text,value) through direct runner queries/taps forclick,get,is, and the firstwaitprobe, while preserving snapshot fallback for misses and transport failures.wait/findsnapshot polling fresh, so the 750ms snapshot cache cannot return stale UI during selector polling.appBundleIdis known, avoiding the visible helper-app hop.Touched scope: 64 files. Scope expanded beyond the original benchmark prototype because the comparison exposed iOS runner startup, selector fallback, gesture, and text-entry reliability issues that affected the measured path.
Validation
Validated with cache-focused unit coverage, selector/interaction unit coverage, tooling checks, XCTest builds, and repeated iOS benchmark runs.
Checks that passed:
pnpm exec vitest run src/platforms/ios/__tests__/runner-client.test.ts src/platforms/ios/__tests__/runner-xctestrun.test.ts src/platforms/ios/__tests__/index.test.ts src/daemon/handlers/__tests__/snapshot-handler.test.tspnpm exec vitest run src/daemon/handlers/__tests__/interaction.test.ts src/daemon/handlers/__tests__/snapshot-handler.test.ts src/utils/__tests__/interactors.test.tsnode --check scripts/write-xcuitest-cache-metadata.mjspnpm build:xcuitestpnpm formatpnpm check:quickzsh -n .tmp/maestro-prototype/run-ios-benchmark.zshgit diff --checkCache reliability notes:
pnpm build:xcuitest.Latest serial benchmark, after dropping one local close outlier:
Parallel benchmark mode is also available for visual side-by-side inspection, but it is not the fair timing source on this machine: under three-simulator load the local runner replay stayed stable around 13.7s while app readiness moved between
openand explicitwait.