mcpField
P
performance-audit

performance-audit

github.com/patrickserranoTesting & quality1366 installsUpdated 41w ago
Repository

About performance-audit

A SwiftUI performance-audit skill for developers. It reviews view code and data flow for common bottlenecks, then guides profiling with Instruments and suggests fixes and follow-up verification.

Key features

  1. 01Review view invalidation from state changes
  2. 02Find unstable list identity
  3. 03Spot expensive work in body
  4. 04Guide profiling with Instruments
  5. 05Suggest fixes and baseline comparisons

Use cases

  1. 01Investigate stutters during scrolling or navigation
  2. 02Review SwiftUI view code and data flow
  3. 03Verify optimizations using performance captures

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/patrickserrano/skills --skill performance-audit

After installing, type/performance-auditin Claude Code to confirm it loaded.

Details

From the project README

SwiftUI Performance Audit

Overview

Audit SwiftUI view performance from instrumentation and baselining to root-cause analysis and concrete remediation steps.

Workflow Decision Tree

  1. If user provides code: Start with Code-First Review
  2. If user only describes symptoms: Ask for minimal code/context, then Code-First Review
  3. If code review is inconclusive: Guide user to profile with Instruments

1. Code-First Review

Collect
  • Target view/feature code
  • Data flow: state, environment, observable models
  • Symptoms and reproduction steps
Focus On
  • View invalidation storms from broad state changes
  • Unstable identity in lists (id churn, UUID() per render)
  • Heavy work in body (formatting, sorting, image decoding)
  • Layout thrash (deep stacks, GeometryReader, preference chains)
  • Large images without downsampling
  • Over-animated hierarchies (implicit animations on large trees)
Provide
  • Likely root causes with code references
  • Suggested fixes and refactors
  • Minimal repro or instrumentation suggestion if needed

2. Guide User to Profile

If code review is inconclusive, explain how to collect data:

  1. Use SwiftUI template in Instruments (Release build)
  2. Reproduce the exact interaction (scroll, navigation, animation)
  3. Capture SwiftUI timeline and Time Profiler
  4. Export or screenshot relevant lanes and call tree

Ask for:

  • Trace export or screenshots
  • Device/OS/build configuration

3. Common Code Smells (and Fixes)

Expensive formatters in body

Bad:

var body: some View {
    let formatter = NumberFormatter()  // Slow allocation every render
    Text(formatter.string(from: value))
}

Good:

final class Formatters {
    static let number = NumberFormatter()
}

var body: some View {
    Text(Formatters.number.string(from: value))
}
Computed properties with heavy work

Bad:

var filtered: [Item] {
    items.filter { $0.isEnabled }  // Runs every body eval
}

Good:

@State private var filtered: [Item] = []

.onChange(of: items) {
    filtered = items.filter { $0.isEnabled }
}
Sorting/filtering in ForEach

Bad:

ForEach(items.sorted(by: sortRule)) { item in
    Row(item)
}

Good:

let sortedItems = items.sorted(by: sortRule)  // Compute once
ForEach(sortedItems) { item in
    Row(item)
}
Unstable identity

Bad:

ForEach(items, id: \.self) { item in  // \.self may not be stable
    Row(item)
}

Good:

ForEach(items, id: \.stableID) { item in
    Row(item)
}
Image decoding on main thread

Bad:

Image(uiImage: UIImage(data: data)!)

Good:

// Decode/downsample off main thread, cache the result
@State private var image: UIImage?

.task {
    image = await ImageLoader.load(data: data, targetSize: size)
}
Broad dependencies in observable models

Bad:

@Observable class Model {
    var items: [Item] = []
}

var body: some View {
    Row(isFavorite: model.items.contains(item))  // Entire array dependency
}

Good:

// Granular view models or per-item state to reduce update fan-out

4. Remediation Strategies

IssueFix
Broad state changesNarrow scope with @State/@Observable closer to leaves
Unstable identitiesUse stable, unique IDs for ForEach
Heavy work in bodyPrecompute, cache, move to @State
Expensive subtreesUse equatable() or value wrappers
Large imagesDownsample before rendering
Layout complexityReduce nesting, use fixed sizing where possible

5. Verify

Ask user to re-run same capture and compare with baseline:

  • CPU usage
  • Frame drops
  • Memory peak

Output Format

Provide:

  1. Metrics table (before/after if available)
  2. Top issues (ordered by impact)
  3. Proposed fixes with estimated effort

Profiling Commands

# Build for profiling
xcodebuild -scheme MyApp -configuration Release -destination 'platform=iOS Simulator,name=iPhone 15 Pro' build

# Open in Instruments
open -a Instruments

Instruments Checklist

  • Use Release build (not Debug)
  • Select SwiftUI template
  • Reproduce exact problematic interaction
  • Look at SwiftUI timeline for body evaluations
  • Check Time Profiler for hot spots
  • Note frame rate drops in Animation timeline

Comments

Markdown supported