| name | ios-performance-optimize |
| description | Guides iOS performance optimization through a systematic five-phase methodology from profiling to verification. Use when optimizing app launch time, reducing memory usage, improving rendering performance, reducing app size, or addressing any performance-related issues in iOS applications. |
iOS 性能优化
核心原则
先量化问题,再定位瓶颈,理解根因后优化,优化后必须验证提升。
性能优化不是凭感觉改代码,而是一个数据驱动的工程过程。好的性能优化需要做到三件事:
- 量化现状 — 用数据描述当前性能,而非"感觉有点慢"
- 精准定位 — 找到真正的瓶颈,而非猜测热点
- 验证提升 — 用同样的指标证明优化有效,而非"感觉快了"
优化决策原则:
- 投入产出比优先 → 优化收益最大的瓶颈
- 可维护性不可牺牲 → 性能与代码质量的平衡
- 回归风险必须可控 → 优化不能引入新问题
- 数据说话 → 每一步都需要量化证据
绝对禁止:
- 未量化就优化("我觉得这里慢"不是依据)
- 过早优化(没有性能问题时不要为了"可能快一点"而牺牲可读性)
- 牺牲可读性换微小性能(0.1ms 的提升不值得写出难以维护的代码)
- 只优化不验证(无法证明提升的优化等于没优化)
- 在模拟器上做性能测试(模拟器的 CPU/GPU 与真机完全不同)
- 一次优化太多点(无法判断哪个改动有效)
复杂度速判
在进入五阶段流程前,先评估优化任务的复杂度:
| 等级 | 判断标准 | 流程路径 | 典型场景 |
|---|
| S(小型) | 瓶颈已知、改动 < 20 行、影响范围单一 | 阶段一 → 阶段四 → 阶段五 | 已知图片未降采样、明显的主线程阻塞、缺少缓存 |
| M(中型) | 需要 profiling 定位、涉及 2-5 个文件 | 完整五阶段流程 | 列表滚动卡顿、启动耗时优化、内存峰值过高 |
| L(大型) | 跨模块/架构级/需要重构、涉及多个性能维度 | 完整五阶段 + 方案评审 | 全链路启动优化、架构级内存治理、包体积瘦身 |
特别规则: 涉及线上 OOM 或启动崩溃的性能问题一律按 M 级及以上 处理。
五阶段流程
输入判断
当用户描述模糊时(如"App 有点慢"、"性能不好"),先通过以下问题引导确认性能维度,再进入五阶段流程:
- "慢"体现在哪里? → 启动慢 / 页面加载慢 / 滚动卡顿 / 操作响应慢
- 什么场景下出现? → 特定页面 / 数据量大时 / 弱网环境 / 长时间使用后
- 影响范围多大? → 所有用户 / 特定设备 / 特定系统版本
- 有没有量化数据? → Instruments 数据 / MetricKit 报告 / 用户反馈统计
- 优化目标是什么? → 具体数值(如启动 < 1s)/ 相对提升(如快 50%)
明确性能维度后,进入对应的五阶段流程。如果用户能提供 Instruments trace 文件或具体的性能指标,可直接跳到阶段二。
阶段一:性能基线建立
量化当前性能指标,建立优化前的基准数据。没有基线就没有对比,没有对比就无法证明优化有效。
关键动作:
- 确定要优化的性能维度(启动/内存/渲染/包体积/网络/电量)
- 选择正确的测量工具和方法 → 参见 Topic Router 和
references/instruments-guide.md
- 在真机上采集基线数据(至少 3 次取均值)
- 记录测试环境(设备型号、系统版本、网络条件、数据量)
基线数据模板:
性能维度:[启动耗时 / 内存峰值 / 帧率 / 包体积 / ...]
测试设备:[iPhone XX, iOS XX]
测试条件:[冷启动 / 列表 1000 条数据 / 弱网 / ...]
基线数值:[具体数值 + 单位]
目标数值:[期望达到的数值]
测量方式:[Instruments 模板 / 自定义埋点 / MetricKit]
行业基准参考值:
| 指标 | 良好 | 可接受 | 需优化 |
|---|
| 冷启动 | < 1s | < 2s | > 3s |
| 帧率 | 60fps | > 55fps | < 45fps |
| 内存 | < 100MB | < 200MB | > 300MB |
| 包体积 | < 50MB | < 100MB | > 200MB |
以上为通用参考值,实际标准应根据 App 类型和目标用户设备调整。低端设备(如 iPhone 8)应以更严格的标准测试。
门控输出: 基线数据已采集,优化目标已量化。没有基线数据不进入下一阶段。
阶段二:瓶颈定位
使用性能分析工具精确定位热点,而不是凭经验猜测。
关键动作:
- 根据性能维度选择对应的 Instruments 模板 →
references/instruments-guide.md
- 录制性能数据,关注异常区间
- 分析 Call Tree / Allocations / 渲染管线,找到具体的热点函数或资源
- 区分主线程瓶颈和后台线程瓶颈
- 列出所有候选瓶颈点,按耗时/影响排序
门控输出: 瓶颈列表已生成(函数/文件/行号 + 耗时/内存占用),按优先级排序。无法定位瓶颈则不进入下一阶段。
阶段三:根因分析
理解瓶颈背后的为什么,而不仅仅是是什么。
关键动作:
- 对每个瓶颈点分析其根本原因
- 区分"代码问题"和"架构问题"
- 参考对应的 reference 文件理解常见根因 → 参见 Topic Router
- 用一句话描述根因:"因为 X,导致 Y 占用了 Z 资源"
根因分类:
- 算法/数据结构不当 — O(n²) 循环、频繁数组拷贝
- 资源使用不当 — 未降采样的图片、未复用的 Cell
- 线程调度不当 — 主线程做 I/O、过度线程切换
- 架构设计问题 — 过度通知、不必要的数据拷贝链
- 系统 API 使用不当 — 错误的绘制方式、离屏渲染
门控输出: 每个瓶颈点的根因已分析清楚,能用一句话描述。根因不清楚则不进入优化阶段。
阶段四:实施优化
按优先级逐个优化,每优化一个点就验证一次效果。
关键动作:
- 按投入产出比排序,优先优化收益最大的瓶颈
- 一次只优化一个点,便于衡量每个改动的效果
- 参考对应的 reference 文件获取优化方案 → 参见 Topic Router
- 保持代码可读性,必要时添加注释说明优化意图
- 每个优化点完成后立即测量效果
优化原则:
- 最小改动原则 — 只改必要的部分
- 可回退原则 — 确保优化可以安全回退
- 不破坏功能 — 性能优化不能改变业务逻辑
- 逐步验证 — 每步优化后测量,确认有效再继续
门控输出: 优化代码已实现,单点测量数据已采集。优化无效或引入问题则回退并重新分析。
阶段五:验证与回归
确认整体优化效果,确保没有副作用。
关键动作:
- 在与基线相同的条件下重新测量所有指标
- 对比基线数据,计算提升幅度
- 运行完整功能测试,确保优化未破坏任何功能
- 检查边界场景(低端设备、大数据量、弱网环境)
- 输出优化报告
优化报告模板:
## 优化报告
优化维度:[启动耗时 / 内存 / 渲染 / ...]
测试设备:[iPhone XX, iOS XX]
| 指标 | 优化前 | 优化后 | 提升幅度 |
|------|--------|--------|---------|
| [指标名] | [数值] | [数值] | [百分比] |
优化措施摘要:
1. [措施 + 效果]
回归验证:
- [ ] 功能测试通过
- [ ] 边界场景验证
- [ ] 低端设备验证
门控输出: 优化报告已生成,提升幅度已量化,回归测试通过。未达目标则回到阶段二重新分析。
Topic Router
| 性能类型 | 主要参考文件 | 辅助参考 |
|---|
| 启动耗时(冷启动/温启动) | references/launch-optimization.md | references/instruments-guide.md(App Launch) |
| 内存占用 / OOM | references/memory-optimization.md | references/instruments-guide.md(Allocations) |
| 内存泄漏 | references/memory-optimization.md → 内存泄漏排查 | references/instruments-guide.md(Leaks) |
| 列表滚动卡顿 / 帧率 | references/rendering-optimization.md | references/instruments-guide.md(Core Animation) |
| 离屏渲染 | references/rendering-optimization.md → 离屏渲染 | references/instruments-guide.md(Core Animation) |
| SwiftUI 渲染性能 | references/rendering-optimization.md → SwiftUI 渲染优化 | references/instruments-guide.md(Time Profiler) |
| 包体积 / App 大小 | references/app-size-optimization.md | — |
| 网络请求性能 | references/network-battery-optimization.md → 网络优化 | — |
| 电量消耗 | references/network-battery-optimization.md → 电量优化 | references/instruments-guide.md(Energy Log) |
| Swift Concurrency 性能 | references/concurrency-optimization.md | references/instruments-guide.md(Time Profiler) |
| 数据库 / Core Data / SwiftData | references/database-optimization.md | references/instruments-guide.md(Time Profiler) |
| 通用性能分析 | references/instruments-guide.md | 按定位结果选择对应 reference |
红旗信号表
| 违规行为 | 为什么是错误的 | 正确做法 |
|---|
| 未量化就开始优化 | 无法判断优化是否有效 | 先建立基线数据 |
| 在模拟器上做性能测试 | 模拟器使用 Mac CPU/GPU,结果不可信 | 必须在真机上测试 |
| 一次优化多个点 | 无法区分哪个改动有效 | 逐个优化、逐个验证 |
| 凭猜测优化而非 profiling | 80% 的瓶颈出现在 20% 的代码中 | 用 Instruments 找到真正的瓶颈 |
| 牺牲可读性换微小提升 | 维护成本远大于性能收益 | 只在收益显著时做取舍 |
| 过度缓存不设上限 | 缓存本身变成内存问题 | 设置缓存上限和淘汰策略 |
| 优化后不做回归测试 | 性能优化可能破坏功能 | 完整功能回归验证 |
| 只测最好情况不测边界 | 低端设备/大数据才是性能瓶颈 | 用最低支持设备 + 极端数据测试 |
用 asyncAfter 解决性能问题 | 延迟执行不等于性能优化 | 找到正确的异步/懒加载时机 |
| 优化后不更新文档 | 后续维护者不知道为何这么写 | 关键优化添加注释说明意图 |
输出格式规范
瓶颈报告(阶段二输出)
瓶颈 #N:[简短描述]
文件:[路径:行号] 函数:[函数名]
指标:[耗时 XXms / 内存 XXmb / 帧率 XX fps]
优先级:[高/中/低](基于影响程度和优化难度)
优化方案(阶段四输出)
针对瓶颈 #N:[描述]
根因:因为 [X],导致 [Y 占用了 Z 资源]
方案:[具体优化措施]
预期效果:[预计可降低 XX% / 减少 XXms]
风险:[可能影响的功能点]
最终优化报告(阶段五输出)
## 性能优化报告
### 优化概述
[一句话概括本次优化]
### 量化结果
| 指标 | 优化前 | 优化后 | 提升 |
|------|--------|--------|------|
| ... | ... | ... | ... |
### 优化措施
1. [措施 + 效果]
### 回归验证
- [ ] 功能测试通过
- [ ] 低端设备验证
- [ ] 边界场景验证
### 后续建议
[如有进一步优化空间,列出建议]
与其他 Skill 的协作
- ios-code-review:优化代码提交后,使用 code-review 审查性能优化的正确性和代码质量
- ios-issue-fix:性能问题本质是 Bug 时(如 OOM 崩溃),先用 issue-fix 定位根因,再用本 skill 优化
- ios-refactor:当性能问题根因是架构层面时,需要先重构再优化