性能
性能问题按这个顺序查
先复现并量化,再改一处。Debug 下的好转,多数不能当结论。
性能改动最浪费时间的方式,是同时关几个 SDK、换一种图片库、再把列表改成手动布局,然后觉得“好像顺了”。下次退步时,没有人知道该看哪。
顺序
- 写成可复现的步骤:哪台系统、冷启动还是热启动、第几次滚动、数据量多大。
- 选一个数:启动到第一帧、滚动时的 hitch 毫秒、这一页的内存峰值、IPA 大小。一次只盯一个。
- 用 Release 配置,脱离调试器再量。需要符号时用 dSYM,而不是长期在 Debug 里优化。
- 缩小范围。signpost 或 Time Profiler 指出一个函数之后,只改这个函数。
- 同一路径再量一次。数字没有变,就回退这处改动,不要留在分支里。
实验室和线上
Instruments 适合你能复现的问题。线上的慢启动、挂起,用 MetricKit 看分布,而不是看某一个同事的机器。实验室里快 200ms,线上 p90 没动,就说明你优化的那条路径不是用户在走的那条。
import os
let log = OSLog(subsystem: "cn.myjzsfly.app", category: "feed")
func reloadFeed() {
let signpost = OSSignposter(logHandle: log)
let state = signpost.beginInterval("reload")
defer { signpost.endInterval("reload", state) }
// 只包住这一次刷新的真正工作
}
子系统用你自己的反向域名,类别用功能名。区间名字稳定,后面才能把几次录制放在一起比。
容易误判的情况
- 第一次安装后的启动包含缓存建立,和日常启动不是同一个数。
- 模拟器的 GPU 和内存行为不能代表真机。
- 编译器优化在 Debug 基本没开,很多“算法优化”只在 Release 才看得到。
- 主线程看起来空闲,但 hitch 在 GPU,那是离屏渲染或图层太大,不是 JSON。
留一个最小记录:问题、指标、改动、前后数字。下一篇笔记只要能接上这个记录,就比再收藏十篇泛泛的优化清单有用。