mcpField
P
performance-audit

performance-audit

github.com/patrickserrano测试与质量1366 次安装41 周前更新
代码仓库

关于 performance-audit

面向 SwiftUI 开发者的性能审查技能,先从视图代码和数据流排查常见瓶颈,再在需要时引导使用 Instruments 分析,并提出修复与复测方法。

主要功能

  1. 01检查状态变更导致的视图刷新
  2. 02排查列表身份不稳定问题
  3. 03发现 body 中的高开销工作
  4. 04指导使用 Instruments 分析
  5. 05提供修复建议与基线复测

适用场景

  1. 01定位滚动或导航中的卡顿原因
  2. 02审查 SwiftUI 视图代码和数据流
  3. 03依据性能采样验证优化效果

安装

复制下面的命令,在终端中运行。

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

安装后在 Claude Code 中输入/performance-audit确认已加载。

详细介绍

SwiftUI 性能审计

概述

从埋点和基线测试,到根因分析和具体的修复步骤,对 SwiftUI 视图性能进行审计。

工作流决策树

  1. 如果用户提供了代码:从代码优先审查开始
  2. 如果用户只描述了症状:请求提供最少量的代码和上下文,然后进行代码优先审查
  3. 如果代码审查无法得出结论:引导用户使用 Instruments 进行性能分析

1. 代码优先审查

收集
  • 目标视图/功能代码
  • 数据流:状态、环境、可观察模型
  • 症状和复现步骤
重点检查
  • 广泛的状态变更引发的视图失效风暴
  • 列表中的身份不稳定(id 频繁变化、每次渲染都调用 UUID())
  • body 中的繁重工作(格式化、排序、图像解码)
  • 布局抖动(嵌套层级过深、GeometryReader、偏好值链)
  • 未进行降采样的大尺寸图像
  • 动画过多的视图层级(大型视图树上的隐式动画)
提供
  • 可能的根因及相关代码位置
  • 建议的修复方案和重构方法
  • 必要时提供最小复现示例或埋点建议

2. 引导用户进行性能分析

如果代码审查无法得出结论,请说明如何收集数据:

  1. 在 Instruments 中使用 SwiftUI 模板(Release 构建)
  2. 复现完全相同的交互(滚动、导航、动画)
  3. 捕获 SwiftUI 时间线和 Time Profiler 数据
  4. 导出或截取相关轨道和调用树

请用户提供:

  • 跟踪导出文件或截图
  • 设备/OS/构建配置

3. 常见代码异味(及修复方法)

在 body 中使用开销大的格式化器

错误示例:

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

正确示例:

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

var body: some View {
    Text(Formatters.number.string(from: value))
}
执行繁重工作的计算属性

错误示例:

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

正确示例:

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

.onChange(of: items) {
    filtered = items.filter { $0.isEnabled }
}
在 ForEach 中排序/筛选

错误示例:

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

正确示例:

let sortedItems = items.sorted(by: sortRule)  // Compute once
ForEach(sortedItems) { item in
    Row(item)
}
身份不稳定

错误示例:

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

正确示例:

ForEach(items, id: \.stableID) { item in
    Row(item)
}
在主线程上解码图像

错误示例:

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

正确示例:

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

.task {
    image = await ImageLoader.load(data: data, targetSize: size)
}
可观察模型中的依赖范围过广

错误示例:

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

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

正确示例:

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

4. 修复策略

问题修复方法
状态变更影响范围过广使用 @State/@Observable 将作用范围缩小到更靠近叶节点的位置
身份不稳定为 ForEach 使用稳定且唯一的 ID
body 中的繁重工作预先计算、缓存,或移至 @State
开销大的子树使用 equatable() 或值包装器
大尺寸图像渲染前进行降采样
布局复杂减少嵌套,并尽可能使用固定尺寸

5. 验证

请用户重新执行相同的性能捕获,并与基线对比:

  • CPU 使用率
  • 丢帧情况
  • 内存峰值

输出格式

提供:

  1. 指标表(如有数据,包含修复前后对比)
  2. 主要问题(按影响程度排序)
  3. 建议的修复方案及预估工作量

性能分析命令

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

# Open in Instruments
open -a Instruments

Instruments 检查清单

  • 使用 Release 构建(而非 Debug)
  • 选择 SwiftUI 模板
  • 复现完全相同的问题交互
  • 查看 SwiftUI 时间线中的 body 求值情况
  • 使用 Time Profiler 检查热点
  • 在 Animation 时间线中记录帧率下降情况

评论

支持 Markdown