先确定测量口径
性能数字需要带上设备、系统版本、应用构建类型、操作路径和采样方式。开发机上的一次结果只能描述那次运行,不能直接作为所有设备的固定标准。建立基线时,把冷启动、首屏操作、长列表滚动等场景分开记录,再做同条件对比。
| 问题 | 建议观察项 | 可用工具 |
|---|---|---|
| 启动慢 | TTID、TTFD 与启动 trace | Macrobenchmark、Perfetto |
| 滚动或动画掉帧 | 帧耗时、deadline miss 与 jank | FrameTimingMetric、Perfetto |
| 内存持续增长 | Java/Kotlin heap、native allocation、RSS 及对象引用链 | Android Studio Profiler、heap dump、Perfetto |
| ANR | 主线程阻塞区间、ANR trace 与 Android vitals 发生率 | Play Console、Perfetto、系统 trace |
帧率应看 deadline 和 jank
不要把 60 FPS 当作适用于所有设备的唯一目标。每帧可用时间受屏幕刷新率影响;刷新率为 60 Hz 时,一个刷新周期约 16.7 ms,90 Hz 时约 11.1 ms,120 Hz 时约 8.3 ms。实际还需检查帧是否错过 deadline,以及掉帧集中在哪个交互和设备上。
用 Macrobenchmark 的 FrameTimingMetric 或 Perfetto 记录代表性操作,查看 UI 与 RenderThread 的工作、长帧和帧延迟。先缩小到具体页面或动画,再检查主线程计算、过度绘制、布局/重组频率、图片解码和同步 I/O;不要只根据平均 FPS 判断流畅度。
启动与主线程排查
用 StartupTimingMetric 在固定设备和启动路径下采集冷启动 TTID/TTFD,并保留 benchmark 输出与 trace。TTID 表示首帧显示时间,TTFD 取决于应用何时报告主要内容已可用;若没有合理的 reportFullyDrawn 标记,TTFD 不能代表真实首屏就绪。
沿启动 trace 检查 Application.onCreate()、ContentProvider、依赖注入容器和首屏代码中的同步工作。只有确认任务不影响首屏正确性后,才考虑延迟初始化或按需加载。AndroidX App Startup 可以帮助梳理初始化器及依赖顺序,本身并不会自动减少启动耗时。
内存分析要区分来源
Java/Kotlin heap、native heap、图形缓冲区和进程 RSS 描述的范围不同,不能用一个数代替完整的内存状态。先重复触发同一操作并观察曲线是否回落,再用 heap dump、allocation recording 或 Perfetto 确认对象由谁持有;图片、Bitmap、缓存和 JNI/native 分配也要分别检查。
泄漏判断应沿引用链找仍然存活的 Activity、View、监听器、协程或缓存条目。为组件设置与生命周期匹配的取消和清理逻辑,修复后在相同步骤下复测。Android vitals 的内存质量阈值会按设备内存档位和应用状态区分,因此不存在适用于所有 Android 应用的固定 256 MB 上限。
ANR 指标不要误读
ANR 调查从 Play Console 的 Android vitals 和对应 trace 开始,检查主线程是否被锁、Binder、磁盘 I/O、长计算或同步等待阻塞。缩短阻塞后,还要复测相同用户路径,并留意后台任务和进程状态。
Google Play 当前把整体用户感知 ANR 率 0.47% 列为不良行为阈值之一,单设备阈值另有定义。它是 Android vitals 的质量判定门槛,不是通用性能目标,也不意味着低于该值就不必处理 ANR。应用自己的告警目标应结合受影响用户、版本、设备和业务路径设定。
把优化结果做成可复现记录
每次只调整一类工作,并保存提交版本、设备与系统信息、构建方式、操作步骤、原始 trace 和多次运行结果。Baseline Profile、延迟初始化或缓存策略都应在应用自身场景下测量收益与回归;没有本项目数据时,不把文档中的效果写成固定百分比承诺。
本文按官方工具与指标文档整理排查流程,没有声称完成某个应用的真机调优或前后 benchmark。
