native-app-profiling
GitHub通过 CLI 使用 xctrace 对 macOS/iOS 原生应用进行性能分析,无需打开 Instruments。涵盖记录 CPU 采样、导出数据、符号化堆栈及识别性能热点的完整工作流。
Trigger Scenarios
Install
npx skills add termio-sh/termio --skill native-app-profiling -g -y
SKILL.md
Frontmatter
{
"name": "native-app-profiling",
"description": "Profile native macOS\/iOS apps using Time Profiler via CLI (xctrace). Use when asked to identify performance hotspots, profile CPU usage, or diagnose slow code paths without opening Instruments."
}
Native App Performance Profiling (CLI)
Overview
Record Time Profiler via xctrace, extract samples, symbolicate, and identify hotspots without opening Instruments.
Quick Start
1) Record Time Profiler
Attach to running process:
# Get the PID first
pgrep -x "AppName"
# Record for 90 seconds
xcrun xctrace record \
--template 'Time Profiler' \
--time-limit 90s \
--output /tmp/App.trace \
--attach <pid>
Launch and record:
xcrun xctrace record \
--template 'Time Profiler' \
--time-limit 90s \
--output /tmp/App.trace \
--launch -- /path/to/App.app/Contents/MacOS/App
2) Export Time Samples
List available schemas in the trace:
xcrun xctrace export --input /tmp/App.trace --toc
Export time profile data:
xcrun xctrace export \
--input /tmp/App.trace \
--xpath '/trace-toc/run/data/table[@schema="time-profile"]' \
--output /tmp/time-profile.xml
3) Get Load Address for Symbolication
While the app is running, get the __TEXT segment load address:
vmmap <pid> | grep "__TEXT"
Look for the load address (typically starts with 0x1...).
4) Symbolicate Stack Frames
Use atos to symbolicate addresses:
atos -o /path/to/App.app/Contents/MacOS/App -l 0x100000000 <address>
Workflow Notes
- Correct binary: Confirm you're profiling the right build (local vs /Applications)
- Trigger the slow path: During capture, perform the action that's slow
- Capture duration: If stacks are empty, capture longer or avoid idle time
- Symbol matching: Binary symbols must match the trace (same build)
Available Templates
List all profiling templates:
xcrun xctrace list templates
Common templates:
Time Profiler- CPU samplingAllocations- Memory allocationsLeaks- Memory leak detectionSystem Trace- System-level activityAnimation Hitches- UI performance
Common Commands
| Task | Command |
|---|---|
| List templates | xcrun xctrace list templates |
| List devices | xcrun xctrace list devices |
| Record help | xcrun xctrace help record |
| Export help | xcrun xctrace help export |
| Get PID | pgrep -x "AppName" |
| Get load address | vmmap <pid> | grep __TEXT |
| Symbolicate | atos -o <binary> -l <load-addr> <address> |
Analyzing Results
Manual Analysis
- Export the trace to XML
- Parse the call tree data
- Look for frames with high sample counts
- Focus on your app's code (filter out system frameworks)
Identify Hotspots
Look for:
- Functions with high self-time (time spent in function itself)
- Deep call stacks indicating inefficient algorithms
- Repeated patterns suggesting optimization opportunities
Gotchas
- ASLR: Runtime
__TEXTload address changes each launch - get it fromvmmap - Build mismatch: Symbols must match the exact build that was profiled
- Idle time: Profiling idle app produces empty/useless data
- Permissions: May need to run with
sudofor some operations
iOS Profiling
For iOS apps on simulator:
xcrun xctrace record \
--template 'Time Profiler' \
--device <simulator-udid> \
--time-limit 60s \
--output /tmp/iOS-App.trace \
--launch -- <bundle-id>
Get simulator UDID:
xcrun simctl list devices | grep Booted
Automation Script
Basic recording script:
#!/bin/bash
set -e
APP_NAME="$1"
DURATION="${2:-60}"
OUTPUT="${3:-/tmp/$APP_NAME.trace}"
if [ -z "$APP_NAME" ]; then
echo "Usage: $0 <app-name> [duration-seconds] [output-path]"
exit 1
fi
PID=$(pgrep -x "$APP_NAME" || true)
if [ -n "$PID" ]; then
echo "Attaching to running $APP_NAME (PID: $PID)"
xcrun xctrace record \
--template 'Time Profiler' \
--time-limit "${DURATION}s" \
--output "$OUTPUT" \
--attach "$PID"
else
echo "App not running. Please start $APP_NAME first."
exit 1
fi
echo "Trace saved to: $OUTPUT"
echo "To analyze: xcrun xctrace export --input $OUTPUT --toc"
Checklist
- Correct binary path identified
- App running or launch command ready
- Slow path reproducible
- Trace recorded during problematic behavior
- Load address captured for symbolication
- Results analyzed for hotspots
Version History
- 2dfed32 Current 2026-08-27 09:02


