Claude
Skills
Sign in
Back

performance-profiling

Included with Lifetime
$97 forever

Instruments integration and performance analysis workflows for iOS apps. Use when profiling CPU usage, memory allocation, network activity, or energy consumption. Covers Time Profiler, Allocations, Leaks, Network instruments, and performance optimization strategies.

General

What this skill does


# Performance Profiling Skill

**Comprehensive guide to iOS performance analysis and optimization**

## Overview

Performance profiling is the systematic analysis of an iOS app's runtime behavior to identify bottlenecks, memory issues, network inefficiencies, and energy consumption patterns. This Skill guides you through using Instruments templates, interpreting profiling data, and applying optimization strategies.

**Key Tools:**
- Instruments (Xcode's profiling suite)
- xcodebuild for profiling builds
- Performance metrics analysis
- Memory graph debugging

## When to Use This Skill

Use performance profiling when:

1. **App Performance Issues**
   - Slow app launch times
   - Choppy scrolling or animations
   - UI freezing or unresponsiveness
   - High CPU usage

2. **Memory Problems**
   - Memory leaks detected
   - Growing memory footprint
   - Memory warnings
   - App crashes due to memory pressure

3. **Network Inefficiencies**
   - Slow data loading
   - Excessive network requests
   - Large payload sizes
   - Poor offline handling

4. **Energy Consumption**
   - Battery drain complaints
   - Background processing issues
   - Thermal throttling
   - Energy impact reports

5. **Pre-Release Optimization**
   - Performance regression detection
   - Baseline performance establishment
   - Release candidate validation
   - Performance budget enforcement

## Key Concepts

### Instruments Templates

**Time Profiler**
- Measures CPU usage and call stacks
- Identifies hot paths in code
- Shows function-level performance
- Best for: CPU-bound operations, algorithm optimization

**Allocations**
- Tracks memory allocations and deallocations
- Shows object lifetime and retention
- Identifies memory growth patterns
- Best for: Memory footprint analysis, allocation hotspots

**Leaks**
- Detects memory leaks in real-time
- Shows leaked objects and their origins
- Identifies retain cycles
- Best for: Finding memory leaks, debugging reference cycles

**Network**
- Monitors HTTP/HTTPS traffic
- Shows request/response timing
- Tracks payload sizes
- Best for: API optimization, bandwidth analysis

**Energy Log**
- Measures energy consumption
- Shows CPU, network, display impact
- Identifies battery drain sources
- Best for: Battery life optimization

**Core Animation**
- Analyzes frame rate and rendering
- Shows layer composition issues
- Identifies off-screen rendering
- Best for: Animation optimization, scrolling performance

### Profiling Strategies

**Sampling vs Tracing**

**Sampling (Time Profiler):**
- Periodically captures call stacks
- Low overhead (~5-10%)
- May miss short-lived operations
- Best for: Production-like scenarios

**Tracing (Most other instruments):**
- Records every event
- Higher overhead (10-50%)
- Complete event history
- Best for: Detailed analysis

### Performance Metrics

**Launch Time**
- Pre-main time: Dynamic library loading, +load methods
- Main to first frame: App initialization, first view load
- Target: < 400ms total on device

**Scrolling Performance**
- Frame rate: 60 FPS (16.67ms per frame)
- Hitch ratio: < 5ms hitches per second
- Target: 60 FPS sustained during scrolling

**Memory Footprint**
- Resident memory: Actual physical RAM used
- Dirty memory: Memory written to by app
- Target: Depends on device (< 150MB for low-end devices)

**Network Efficiency**
- Request latency: Time to first byte
- Transfer size: Payload + overhead
- Request frequency: Requests per minute
- Target: < 100KB per request, batch when possible

**Energy Impact**
- CPU time: Processor usage
- Network bytes: Data transferred
- Display time: Screen on time
- Target: "Low" or "Medium" energy impact rating

## Workflows

### CPU Profiling (Time Profiler)

**Goal:** Identify CPU-intensive operations and optimize hot paths

**Step 1: Build for Profiling**

```json
{
  "operation": "build",
  "scheme": "MyApp",
  "configuration": "Release",
  "destination": "platform=iOS,id=<device-udid>",
  "options": {
    "archive_for_profiling": true
  }
}
```

**Why Release Configuration?**
- Enables optimizations
- Reflects production performance
- Removes debug overhead

**Device vs Simulator:**
- Always profile on device for accurate CPU measurements
- Simulator runs on Mac CPU (not representative)

**Step 2: Profile with Instruments**

```bash
# Launch Instruments with Time Profiler template
instruments -t "Time Profiler" \
  -D /path/to/trace.trace \
  -w <device-udid> \
  com.example.MyApp
```

**Manual Approach:**
1. Open Instruments (Xcode → Open Developer Tool → Instruments)
2. Select "Time Profiler" template
3. Choose device and app
4. Click record, perform problematic operations
5. Stop recording

**Step 3: Analyze Call Tree**

**Call Tree Settings:**
- Enable "Separate by Thread"
- Enable "Hide System Libraries" (initially)
- Show "Heaviest Stack Trace"

**Interpret Results:**
- **Self Time**: Time spent in function itself
- **Total Time**: Time including called functions
- **Call Count**: Number of times function called

**Red Flags:**
- Self time > 50ms for UI operations
- High call count for expensive operations
- Unexpected functions in hot path

**Step 4: Optimize**

**Common Optimizations:**
- Reduce algorithm complexity (O(n²) → O(n log n))
- Cache expensive computations
- Move work off main thread
- Use lazy evaluation

**Verification:**
- Profile again after changes
- Compare before/after traces
- Ensure optimization didn't break functionality

### Memory Profiling (Allocations & Leaks)

**Goal:** Identify memory leaks and reduce memory footprint

**Step 1: Build for Profiling**

```json
{
  "operation": "build",
  "scheme": "MyApp",
  "configuration": "Debug",
  "destination": "platform=iOS Simulator,name=iPhone 15",
  "options": {
    "enable_memory_debugging": true
  }
}
```

**Note:** Use Debug for better stack traces, Simulator acceptable for memory profiling

**Step 2: Profile with Allocations**

```bash
# Launch Instruments with Allocations template
instruments -t "Allocations" \
  -D /path/to/allocations.trace \
  -w <simulator-udid> \
  com.example.MyApp
```

**Step 3: Identify Memory Growth**

**Heap Growth Analysis:**
1. Take memory snapshot (Mark Generation)
2. Perform operation (e.g., open/close view controller)
3. Take another snapshot
4. View "Growth" column

**Expected:** Minimal growth after repeated operations
**Red Flag:** Continuous growth with each iteration

**Step 4: Find Leaks**

**Switch to Leaks Instrument:**
```bash
instruments -t "Leaks" \
  -D /path/to/leaks.trace \
  -w <simulator-udid> \
  com.example.MyApp
```

**Interpret Results:**
- Leaks shown in red
- Click leak → See responsible stack trace
- Common causes: Retain cycles, unregistered observers

**Step 5: Debug Retain Cycles**

**Memory Graph Debugger:**
1. Run app in Xcode
2. Click "Debug Memory Graph" button
3. Filter by leaked objects
4. Inspect retain cycle paths

**Common Patterns:**
- Closure capturing self strongly
- Delegate not marked weak
- NSNotificationCenter observers not removed
- Timer retaining target

**Solutions:**
- Use `[weak self]` in closures
- Mark delegates as `weak`
- Remove observers in deinit
- Invalidate timers properly

### Network Profiling

**Goal:** Optimize network requests and reduce data usage

**Step 1: Profile with Network Instrument**

```bash
instruments -t "Network" \
  -D /path/to/network.trace \
  -w <device-udid> \
  com.example.MyApp
```

**Step 2: Analyze Network Activity**

**Key Metrics:**
- **Request Count**: Total number of requests
- **Bytes Transferred**: Upload + download size
- **Duration**: Time from request to completion
- **HTTP Status**: Success/failure codes

**Red Flags:**
- Many small requests (should batch)
- Large payloads (should paginate)
- Sequential requests (should parallelize)
- Redundant requests (should cache)

**Step 3: Optimize Requests**

**Batching:**
```swift
// Before: 10 separate requests
for item in items {
    fetchDetails(for: item)
}

// After: 1 batched request
fetchDetails

Related in General