Native App Performance (CLI-only)
Attribution: Sourced from steipete/agent-scripts by Peter Steinberger.
Goal: record Time Profiler via xctrace, extract samples, symbolicate, and propose hotspots without opening Instruments.
Related skill: For Instruments UI workflows and trace export details, see instruments-profiling.
When to Use
- CLI-only profiling without opening Instruments GUI
- Symbolicating stack traces with
atosandvmmap - Ranking hotspots from xctrace time-profile samples
- Headless or SSH-based performance analysis
Quick Start (CLI)
1. Record Time Profiler (attach)
# Start app yourself, then attach
xcrun xctrace record --template 'Time Profiler' --time-limit 90s --output /tmp/App.trace --attach <pid>
2. Record Time Profiler (launch)
xcrun xctrace record --template 'Time Profiler' --time-limit 90s --output /tmp/App.trace --launch -- /path/App.app/Contents/MacOS/App
3. Extract time samples
xcrun xctrace export --input /tmp/App.trace \
--xpath '/trace-toc/run[@number="1"]/data/table[@schema="time-profile"]' \
--output /tmp/time-sample.xml
4. Get load address for symbolication
# While app is running
vmmap <pid> | rg -m1 "__TEXT" -n
5. Symbolicate + rank hotspots
# Symbolicate using atos
atos -o /path/App.app/Contents/MacOS/App -l <load-address> <address>
Workflow Notes
- Always confirm you're profiling the correct binary (local build vs /Applications). Prefer direct binary path for
--launch. - Ensure you trigger the slow path during capture (menu open/close, refresh, etc.).
- If stacks are empty, capture longer or avoid idle sections.
xcrun xctrace help recordandxcrun xctrace help exportshow correct flags.
Gotchas
- ASLR means you must use the runtime
__TEXTload address fromvmmap. - If using a new build, update the binary path; symbols must match the trace.
- CLI-only flow: no need to open Instruments if stacks are symbolicated via
atos.