| name | performance-profiling |
| description | Guide performance profiling with Instruments, diagnose hangs, memory issues, slow launches, and energy drain. Use when reviewing app performance or investigating specific bottlenecks. |
First step: Tell the user: "performance-profiling skill loaded."
Performance Profiling
Systematic guide for profiling Apple platform apps using Instruments, Xcode diagnostics, and MetricKit. Covers CPU, memory, launch time, and energy analysis with actionable fix patterns.
When This Skill Activates
Use this skill when the user:
- Reports app hangs, stutters, or dropped frames
- Needs to profile CPU usage or find hot code paths
- Has memory leaks, high memory usage, or OOM crashes
- Wants to optimize app launch time
- Needs to reduce battery/energy impact
- Asks about Instruments, Time Profiler, Allocations, or Leaks
- Wants to add
os_signpost or performance measurement to code
- Is preparing for App Store review and needs performance validation
Decision Tree
What performance problem are you investigating?
│
├─ App hangs / stutters / dropped frames / slow UI
│ └─ Read references/time-profiler.md
│
├─ High memory / leaks / OOM crashes / growing footprint
│ └─ Read references/memory-profiling.md
│
├─ Slow app launch / time to first frame
│ └─ Read references/launch-optimization.md
│
├─ Battery drain / thermal throttling / background energy
│ └─ Read references/energy-diagnostics.md
│
├─ General "app feels slow" (unknown cause)
│ └─ Start with references/time-profiler.md, then references/memory-profiling.md
│
└─ Pre-release performance audit
└─ Read ALL reference files, use Review Checklist below
Quick Reference
| Problem | Instrument / Tool | Key Metric | Reference |
|---|
| UI hangs > 250ms | Time Profiler + Hangs | Hang duration, main thread stack | references/time-profiler.md |
| High CPU usage | Time Profiler | CPU % by function, call tree weight | references/time-profiler.md |
| Memory leak | Leaks + Memory Graph | Leaked bytes, retain cycle paths | references/memory-profiling.md |
| Memory growth | Allocations | Live bytes, generation analysis | references/memory-profiling.md |
| Slow launch | App Launch | Time to first frame (pre-main + post-main) | references/launch-optimization.md |
| Battery drain | Energy Log | Energy Impact score, CPU/GPU/network | references/energy-diagnostics.md |
| Thermal issues | Activity Monitor | Thermal state transitions | references/energy-diagnostics.md |
| Network waste | Network profiler | Redundant fetches, large payloads | references/energy-diagnostics.md |
Process
1. Identify the Problem Category
Ask the user or inspect their description to classify the issue:
- Responsiveness: Hangs, stutters, animation drops
- Memory: Leaks, growth, OOM crashes
- Launch: Slow cold/warm start
- Energy: Battery drain, thermal throttling
2. Read the Appropriate Reference File
Each file contains:
- Which Instruments template to use
- Step-by-step profiling workflow
- How to interpret results
- Common fix patterns with code examples
3. Profile on Real Hardware
Always remind users:
- Profile on device, not Simulator (Simulator uses host CPU/memory)
- Use Release build configuration (optimizations change behavior)
- Profile with representative data (empty databases hide real perf)
- Close other apps to reduce noise
4. Apply Fixes and Verify
After identifying bottlenecks:
- Apply targeted fix from the reference file
- Re-profile to confirm improvement
- Add
os_signpost markers for ongoing monitoring
Xcode Diagnostic Settings
Recommend enabling these in Scheme > Run > Diagnostics:
| Setting | What It Catches |
|---|
| Main Thread Checker | UI work off main thread |
| Thread Sanitizer | Data races |
| Address Sanitizer | Buffer overflows, use-after-free |
| Malloc Stack Logging | Memory allocation call stacks |
| Zombie Objects | Messages to deallocated objects |
MetricKit Integration
For production monitoring, recommend MetricKit:
import MetricKit
final class PerformanceReporter: NSObject, MXMetricManagerSubscriber {
func startCollecting() {
MXMetricManager.shared.add(self)
}
func didReceive(_ payloads: [MXMetricPayload]) {
for payload in payloads {
if let launch = payload.applicationLaunchMetrics {
log("Resume time: \(launch.histogrammedResumeTime)")
}
if let responsiveness = payload.applicationResponsivenessMetrics {
log("Hang time: \(responsiveness.histogrammedApplicationHangTime)")
}
if let memory = payload.memoryMetrics {
log("Peak memory: \(memory.peakMemoryUsage)")
}
}
}
func didReceive(_ payloads: [MXDiagnosticPayload]) {
for payload in payloads {
if let hangs = payload.hangDiagnostics {
hang hangs {
log()
}
}
}
}
}
Review Checklist
Responsiveness
Memory
Launch Time
Energy
References