没有 Mac,怎么给 iPhone 做性能分析
我接触过的 iOS 团队里有一半不在 Mac 上。他们写代码,交给 CI,CI 在某个租来的 Mac 上打包。这套流程一直很顺,直到有人问一句“为什么在我手机上这么卡” —— 而答案偏偏藏在一个屋里没人有的机器上才能跑的工具里。
这篇讲的就是这种处境下实际有什么可用。
为什么显而易见的答案不成立
Instruments 是官方的性能分析器。它很好,同时有三个很容易被忽略的前提:
- 只在 macOS 上。
- 一般要有 Xcode 工程,至少要有个能附加上去的构建。
- 大多数有意思的 instrument,都希望你用一个开了调试的包。
第三条即使对有 Mac 的团队也是个隐性问题。Debug 包的优化级别不同、日志不同,有时候代码路径都不同。你分析它的时候,量的是一个没有任何用户在跑的程序。
手机自己就知道这些
工具的讨论里常常跳过一件事:iOS 本来就在测这些。系统会跟踪每个进程的 CPU、内存占用、GPU 利用率、帧呈现、网络字节数和能耗归因 —— 它不得不测,因为调度要用、内存压力下决定杀谁要用、“设置 → 电池”那一页也要用。
这些计数器通过设备自己的服务,向一台用户信任过的电脑开放。这条通道和“电脑给手机做备份”、“电脑给手机装包”是同一条。读它们不需要越狱、不需要在设备上常驻程序、不需要在你的 App 里加 SDK。
这样能拿到什么
连上设备,把范围收到某个 App,你能实时读到:
- 每进程的 CPU(单核百分比)
- 随时间变化的内存占用
- GPU 利用率
- 实际呈现的帧率
- 网络收发字节数
- 能耗影响
这不是 Instruments 的全部。没有分配调用树,没有精确到符号的时间剖析。但它足以回答绝大多数性能排查真正的起点问题:瓶颈在哪个资源上,什么时候?
而这通常就是全部问题
一份卡顿反馈,本质上不是在要一棵调用树,而是在问:你是 CPU 受限、GPU 受限,还是被什么阻塞了。这三种指向的修法完全不同,而图上的四条线就足以区分:
| 卡顿时刻 | 受限于 |
|---|---|
| CPU 冲高、GPU 平 | 主线程上有活 |
| GPU 冲高、CPU 平 | 渲染开销 —— 过度绘制、模糊、离屏渲染 |
| 内存跳升 | 一次大分配,通常是图片解码 |
| 什么都没动 | 阻塞在别处,或者在降频 |
知道自己在哪一行,就知道该去读哪部分代码。之后往往根本不需要调用树;确实需要的时候,你也已经知道该把哪一段交互交给那位有 Mac 的同事。
一个没人预料到会重要的点
在你手上那台设备上做分析,价值低于在用户手上那台设备上做分析。三年前的机型实际帧预算更紧、更早降频、电池容量已经衰减,而桌上的旗舰把这些全掩盖了。
由此带来的现实结果是:能在任意桌面系统上做性能分析,对没有 Mac 的团队来说不只是方便。它意味着你可以在屋里任何一台设备上分析 —— 测试同事的手机、售后备用机、抽屉里那台老机器 —— 而不是只能用配对在那台 Mac 上的两台设备。
一套可执行的流程
- 拿到投诉来源的那台设备,或者你支持的最旧机型。
- 让它凉下来。发烫的手机是另一台手机。
- 把范围收到你的 App。
- 采一段固定交互 —— 同一个列表、同样的距离、十秒。
- 找到下陷,读那一刻的其他曲线。
- 只改一件事,再采同一段交互。
- 对比。
第六步是最常被跳过的。单独一次采集只是一个数字;一次改动前后的两次采集,才是一个结论。
它替代不了什么
把边界说清楚:
- 分配级分析。 内存趋势里看不出来的泄漏,还是需要堆分析工具。
- 符号级 CPU 归因。 知道自己 CPU 受限,不等于知道是哪个函数。
- 网络内容。 字节数不是请求,那是抓包工具的活。
设备级计数器做的事,是把“感觉有点卡”变成“在这台机型上,转场期间是 GPU 受限”。性能排查里绝大部分价值就在这一步,而它在你本来就坐着的这台电脑上就能做到。
