callstack / callstack/agent-device
Add Apple frame-health sampling to perf
- Dominant language
- TypeScript
- Stars
- 4.6k
- Forks
- 299
- Avg merge
- 10h 14m
- Merged PRs (30d)
- 537
Description
## Context
PR #474 adds Android frame-health sampling to `agent-device perf` using `adb shell dumpsys gfxinfo framestats`. Apple platforms currently still expose startup, CPU, and memory metrics, but no native frame/drop health metric.
The Android work settled on an agent-oriented contract: dropped-frame percentage is more useful than FPS for judging transition, animation, and gesture health. The default CLI output stays token-efficient, and richer timing/attribution data remains available in JSON.
## Desired Apple behavior
Add Apple frame-health sampling to `perf` where it can be collected reliably. Keep the same agent-facing shape as Android when possible:
- `droppedFramePercent` as the primary health signal
- `droppedFrameCount` and `totalFrameCount`
- explicit `sampleWindowMs`, `windowStartedAt`, and `windowEndedAt`
- worst dropped-frame windows with relative timestamps, e.g. `+1m20s-+1m22s: 8 missed-deadline frames`
- recent related session actions for correlation with logs and agent interactions
- clear `available: false` reasons when Apple tooling cannot provide trustworthy data
The default non-JSON CLI output on Apple should remain a compact CPU/memory summary until frame health exists, rather than printing FPS-only or misleading placeholder data.
## Implementation insights from Android
- Prefer dropped-frame percentage over FPS; FPS alone hides short jank clusters.
- Raw frame timestamps are important even when an aggregate summary exists. Do not discard attribution data if the source provides both.
- Avoid hard-coded 60Hz deadlines. Infer the display/frame deadline from source data or omit deadline-dependent fields when it cannot be inferred.
- Sampling windows need explicit start/end timestamps. Android resets gfxinfo after `open` and after each successful `perf`; Apple should either reset its source or report a precise collection window.
- Worst windows make the metric actionable for agents because they can correlate `perf --json` output with logs and interaction timelines.
- If attribution is approximate, document the limitation in code and expose enough source metadata to make the confidence clear.
## Investigation candidates
- iOS simulator: evaluate whether `xctrace`/Instruments Core Animation, simulator diagnostics, or another Apple-supported source can provide frame timing or hitch data quickly enough for interactive agent use.
- Physical iOS: current CPU/memory sampling already uses Apple tooling; investigate whether `xctrace` can collect Core Animation/hitch data with acceptable overhead and parseable output.
- macOS app sessions: decide whether this issue includes macOS frame health or whether macOS should be tracked separately.
- React Native render profiling via React DevTools is complementary, not a replacement for native frame health, because it does not directly measure compositor/display missed deadlines.
## Acceptance criteria
- `agent-device perf --json` includes Apple frame-health data only when the source is reliable enough to avoid misleading agents.
- The non-JSON `perf` output stays compact and platform-independent.
- The implementation reports sample start/end and worst jank windows where frame timestamps are available.
- Unavailable cases include clear reasons and do not invent FPS or dropped-frame values.
- Tests cover parser/window behavior and CLI output, and docs explain the Apple support level.
- Validate against the test app on at least one Apple target that supports the chosen source.
Contributor guide
Assessment
This issue has not been assessed yet.