performance-profiling

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

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.
本指南系统介绍如何使用Instruments、Xcode诊断工具和MetricKit对Apple平台应用进行性能分析,涵盖CPU、内存、启动时间和能耗分析,并提供可落地的修复方案。

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
当用户遇到以下情况时,可使用本技能:
  • 反馈应用卡顿、掉帧或运行不流畅
  • 需要分析CPU使用率或找出热点代码路径
  • 存在内存泄漏、内存占用过高或OOM崩溃问题
  • 希望优化应用启动时间
  • 需要降低电池/能耗影响
  • 询问Instruments、Time Profiler、Allocations或Leaks相关内容
  • 希望在代码中添加
    os_signpost
    或性能测量逻辑
  • 准备进行App Store审核,需要验证应用性能

Decision Tree

决策树

What performance problem are you investigating?
├─ App hangs / stutters / dropped frames / slow UI
│  └─ Read time-profiler.md
├─ High memory / leaks / OOM crashes / growing footprint
│  └─ Read memory-profiling.md
├─ Slow app launch / time to first frame
│  └─ Read launch-optimization.md
├─ Battery drain / thermal throttling / background energy
│  └─ Read energy-diagnostics.md
├─ General "app feels slow" (unknown cause)
│  └─ Start with time-profiler.md, then memory-profiling.md
└─ Pre-release performance audit
   └─ Read ALL reference files, use Review Checklist below
What performance problem are you investigating?
├─ App hangs / stutters / dropped frames / slow UI
│  └─ Read time-profiler.md
├─ High memory / leaks / OOM crashes / growing footprint
│  └─ Read memory-profiling.md
├─ Slow app launch / time to first frame
│  └─ Read launch-optimization.md
├─ Battery drain / thermal throttling / background energy
│  └─ Read energy-diagnostics.md
├─ General "app feels slow" (unknown cause)
│  └─ Start with time-profiler.md, then memory-profiling.md
└─ Pre-release performance audit
   └─ Read ALL reference files, use Review Checklist below

Quick Reference

快速参考

ProblemInstrument / ToolKey MetricReference
UI hangs > 250msTime Profiler + HangsHang duration, main thread stacktime-profiler.md
High CPU usageTime ProfilerCPU % by function, call tree weighttime-profiler.md
Memory leakLeaks + Memory GraphLeaked bytes, retain cycle pathsmemory-profiling.md
Memory growthAllocationsLive bytes, generation analysismemory-profiling.md
Slow launchApp LaunchTime to first frame (pre-main + post-main)launch-optimization.md
Battery drainEnergy LogEnergy Impact score, CPU/GPU/networkenergy-diagnostics.md
Thermal issuesActivity MonitorThermal state transitionsenergy-diagnostics.md
Network wasteNetwork profilerRedundant fetches, large payloadsenergy-diagnostics.md
问题工具/Instrument关键指标参考文档
UI卡顿超过250msTime Profiler + Hangs卡顿时长、主线程堆栈time-profiler.md
CPU占用过高Time Profiler各函数CPU占比、调用树权重time-profiler.md
内存泄漏Leaks + Memory Graph泄漏字节数、循环引用路径memory-profiling.md
内存持续增长Allocations活跃字节数、代际分析memory-profiling.md
启动缓慢App Launch首帧时间(main前 + main后)launch-optimization.md
电池耗电快Energy Log能耗影响分数、CPU/GPU/网络占用energy-diagnostics.md
发热问题Activity Monitor热状态转换energy-diagnostics.md
网络资源浪费Network profiler冗余请求、大载荷数据energy-diagnostics.md

Process

流程

1. Identify the Problem Category

1. 确定问题类别

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
询问用户或查看描述对问题进行分类:
  • 响应性:卡顿、掉帧、动画不流畅
  • 内存:泄漏、持续增长、OOM崩溃
  • 启动:冷启动/热启动缓慢
  • 能耗:电池耗电快、热节流

2. Read the Appropriate Reference File

2. 阅读对应参考文档

Each file contains:
  • Which Instruments template to use
  • Step-by-step profiling workflow
  • How to interpret results
  • Common fix patterns with code examples
每个文档包含:
  • 应使用的Instruments模板
  • 分步性能分析流程
  • 结果解读方法
  • 带代码示例的常见修复方案

3. Profile on Real Hardware

3. 在真实硬件上进行分析

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
务必提醒用户:
  • 在真机上分析,不要使用模拟器(模拟器使用主机CPU/内存)
  • 使用Release构建配置(优化会改变运行行为)
  • 使用代表性数据进行分析(空数据库会隐藏真实性能问题)
  • 关闭其他应用以减少干扰

4. Apply Fixes and Verify

4. 应用修复并验证

After identifying bottlenecks:
  • Apply targeted fix from the reference file
  • Re-profile to confirm improvement
  • Add
    os_signpost
    markers for ongoing monitoring
识别瓶颈后:
  • 从参考文档中应用针对性修复方案
  • 重新分析以确认性能提升
  • 添加
    os_signpost
    标记以进行持续监控

Xcode Diagnostic Settings

Xcode诊断设置

Recommend enabling these in Scheme > Run > Diagnostics:
SettingWhat It Catches
Main Thread CheckerUI work off main thread
Thread SanitizerData races
Address SanitizerBuffer overflows, use-after-free
Malloc Stack LoggingMemory allocation call stacks
Zombie ObjectsMessages to deallocated objects
建议在Scheme > Run > Diagnostics中启用以下设置:
设置检测内容
Main Thread Checker主线程外的UI操作
Thread Sanitizer数据竞争
Address Sanitizer缓冲区溢出、野指针访问
Malloc Stack Logging内存分配调用堆栈
Zombie Objects向已释放对象发送消息

MetricKit Integration

MetricKit集成

For production monitoring, recommend MetricKit:
swift
import MetricKit

final class PerformanceReporter: NSObject, MXMetricManagerSubscriber {
    func startCollecting() {
        MXMetricManager.shared.add(self)
    }

    func didReceive(_ payloads: [MXMetricPayload]) {
        for payload in payloads {
            // Launch time
            if let launch = payload.applicationLaunchMetrics {
                log("Resume time: \(launch.histogrammedResumeTime)")
            }
            // Hang rate
            if let responsiveness = payload.applicationResponsivenessMetrics {
                log("Hang time: \(responsiveness.histogrammedApplicationHangTime)")
            }
            // Memory
            if let memory = payload.memoryMetrics {
                log("Peak memory: \(memory.peakMemoryUsage)")
            }
        }
    }

    func didReceive(_ payloads: [MXDiagnosticPayload]) {
        for payload in payloads {
            if let hangs = payload.hangDiagnostics {
                for hang in hangs {
                    log("Hang: \(hang.callStackTree)")
                }
            }
        }
    }
}
对于生产环境监控,推荐使用MetricKit:
swift
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("恢复时间: \(launch.histogrammedResumeTime)")
            }
            // 卡顿率
            if let responsiveness = payload.applicationResponsivenessMetrics {
                log("卡顿时间: \(responsiveness.histogrammedApplicationHangTime)")
            }
            // 内存
            if let memory = payload.memoryMetrics {
                log("峰值内存: \(memory.peakMemoryUsage)")
            }
        }
    }

    func didReceive(_ payloads: [MXDiagnosticPayload]) {
        for payload in payloads {
            if let hangs = payload.hangDiagnostics {
                for hang in hangs {
                    log("卡顿: \(hang.callStackTree)")
                }
            }
        }
    }
}

Review Checklist

评审检查清单

Responsiveness

响应性

  • No synchronous work on main thread > 100ms
  • No file I/O or network calls on main thread
  • Core Data / SwiftData fetches use background contexts for large queries
  • Images decoded off main thread (use
    .preparingThumbnail
    or async decoding)
  • @MainActor
    only on code that truly needs UI access
  • 主线程上无超过100ms的同步操作
  • 主线程上无文件I/O或网络请求
  • Core Data / SwiftData大型查询使用后台上下文
  • 图片解码在主线程外进行(使用
    .preparingThumbnail
    或异步解码)
  • @MainActor
    仅用于真正需要访问UI的代码

Memory

内存

  • No retain cycles (check delegate patterns, closures with
    self
    )
  • Large resources freed when not visible (images, caches)
  • Collections don't grow unbounded (capped caches, pagination)
  • autoreleasepool
    used in tight loops creating ObjC objects
  • 无循环引用(检查代理模式、带
    self
    的闭包)
  • 不可见时释放大型资源(图片、缓存)
  • 集合不会无限增长(设置缓存上限、分页)
  • 在创建ObjC对象的密集循环中使用
    autoreleasepool

Launch Time

启动时间

  • No heavy work in
    init()
    of
    @main App
    struct
  • Deferred non-essential initialization (analytics, prefetch)
  • Minimal dynamic frameworks (prefer static linking)
  • No synchronous network calls at launch
  • @main App
    结构体的
    init()
    中无繁重操作
  • 延迟非必要初始化(分析、预取)
  • 尽量减少动态框架(优先静态链接)
  • 启动时无同步网络请求

Energy

能耗

  • Background tasks use
    BGProcessingTaskRequest
    appropriately
  • Location accuracy matches actual need (not always
    .best
    )
  • Timers use
    tolerance
    to allow coalescing
  • Network requests batched where possible
  • 后台任务合理使用
    BGProcessingTaskRequest
  • 定位精度匹配实际需求(不总是使用
    .best
  • 定时器使用
    tolerance
    允许合并执行
  • 尽可能批量处理网络请求

References

参考资料