提升 App 性能,就是启动更快、滑动流畅、崩溃和 ANR 更少、弱网下也能正常工作,而且要在真实设备上衡量。本文列出关键指标和目标、八个具体步骤,并用一次启动跟踪演示:推迟 SDK 初始化、按视图尺寸解码图片,冷启动中位数从 3.4 秒降到 1.6 秒。
读完你会知道
- 先看真实设备上的数据,再在实验室里剖析
- 首屏用不到的工作全部推迟
- 磁盘、解析、网络都不放在主线程
- 看中位数和第 90 百分位,不看平均数
- 每次发版都跟踪,及早发现回退
提升 App 性能指的是什么?
提升 App 性能,是让移动 App 启动更快、点了马上有反应、滑动流畅、少占内存和电量、在弱网下也能好好工作,而且要以用户真实使用的设备来衡量。它比泛泛的「App 优化」范围小:目标不是直接带来更多注册,而是去掉让用户在走到那一步之前就放弃的技术原因。
性能工作从度量开始。没有真实设备上的基线,就判断不了改动有没有用,最后优化的是开发者手机上容易看到的问题,而不是三年前中端机用户真正受影响的问题。
值得关注的 App 性能指标
| 指标 | 衡量什么 | 常见目标 | 说明 |
|---|---|---|---|
| 冷启动时间 | 进程启动到画出首帧 | 大多数 App 在 2 秒内;Android Vitals 认为 5 秒及以上过长 | 受 Application / AppDelegate 初始化的工作影响最大 |
| 温启动、热启动 | 从后台回到可用页面 | 1 秒内 | 热启动慢,常常是因为重新拉取数据 |
| 帧渲染(卡顿) | 错过屏幕刷新截止时间的帧占比 | 慢帧、冻结帧越少越好 | 60 Hz 下每帧 16.7 毫秒 |
| ANR 率(Android) | 主线程因输入被阻塞 5 秒及以上 | 低于 0.47% 的用户(Android Vitals 不良行为阈值) | iOS 上对应「卡死」 |
| 无崩溃用户占比 | 1 − 崩溃用户 ÷ 活跃用户 | 常见目标 99.5% 以上 | 按版本跟踪 |
| 内存 | 每次会话的峰值和平均内存 | 稳定,会话中不持续上涨 | 持续上涨往往是泄漏 |
| 网络 | 请求延迟、错误率、数据量 | 看接口而定 | 在限速的 3G / 4G 下测试 |
| 安装包大小 | 下载和安装体积 | 尽量小 | 包越大,用流量安装的人越少 |
提升 App 性能的八个步骤
1. 看线上数据,不只看实验室
实验室工具(Android Studio Profiler、Xcode Instruments、Macrobenchmark)用来找原因;真实用户的线上数据告诉你问题在哪、有多大。从正式版收集冷启动、崩溃、ANR 和内存,按机型、系统版本、App 版本拆开。
2. 砍掉冷启动时的工作
列出首帧之前运行的所有东西:SDK 初始化、数据库迁移、配置拉取、依赖注入。首屏用不到的,推迟到首帧之后或用到时再做。Android 上可以用 Baseline Profiles 让运行时预编译热点代码。
3. 让主线程保持空闲
把磁盘读写、JSON 解析、图片解码和网络请求移出主线程。Android 在调试包里打开 StrictMode 抓意外的主线程读写;iOS 用 Main Thread Checker 和卡死报告。
4. 解决渲染卡顿
压平过深的视图层级,别在滚动回调里触发布局,用可复用列表,按视图尺寸解码图片而不是解码原图。先分析慢帧占比最高的页面。
5. 控制内存
页面消失时释放大图,给内存缓存设上限,在长会话里找泄漏。内存不足被系统杀掉,往往只在低内存机型上表现为崩溃。
6. 让网络更宽容
缓存响应,只请求页面需要的字段,压缩数据,设置超时和带退避的重试,刷新时先显示缓存内容。每个关键流程都在限速网络下测一遍。
7. 缩小安装包
去掉没用的资源和库,用 Android App Bundle 和资源目录让设备只下载需要的部分,压缩图片。
8. 防止回退
在持续集成里加启动和帧率基准测试,每次发版后的头几天对比线上指标。性能是一个依赖一个依赖地退回去的。
| 问题 | 可能原因 | 先做什么 |
|---|---|---|
| 冷启动慢 | 启动时初始化 SDK、阻塞式拉取 | 推迟到首帧之后 |
| 滑动卡顿 | 按原图解码、布局层级深 | 按视图尺寸解码、压平布局 |
| ANR | 主线程上读写磁盘或网络 | 移到后台线程 |
| 低内存机型崩溃 | 内存压力、泄漏 | 释放大图、限制缓存 |
先用线上数据找到慢的页面,再用剖析工具复现。
计算示例:冷启动减半
某购物 App(示例数据)在 Android 上冷启动中位数 3.4 秒,3 GB 内存设备的第 90 百分位是 7.8 秒。启动跟踪显示:
| 启动时的工作 | 改前耗时 | 改动 | 改后耗时 |
|---|---|---|---|
| 初始化三个统计、广告 SDK | 900 毫秒 | 改到首帧之后初始化 | 首帧前 0 毫秒 |
| 阻塞式拉取远程配置 | 700 毫秒 | 先用缓存配置,后台刷新 | 40 毫秒 |
| 检查数据库迁移 | 350 毫秒 | 移到后台线程 | 主线程 0 毫秒 |
| 首页信息流图片按原图解码 | 600 毫秒 | 按视图尺寸解码 | 180 毫秒 |
冷启动中位数从 3.4 秒降到 1.6 秒,3 GB 设备的第 90 百分位从 7.8 秒降到 3.9 秒。发版后两周,Android 新用户次日留存从 22% 升到 25%;同一个版本里还有别的改动,所以启动提速很可能是原因之一,但不能确定只有它起了作用。
冷启动中位数
3.4 秒 → 1.6 秒
▲ −53%
3 GB 设备 p90
7.8 秒 → 3.9 秒
▲ −50%
次日留存
22% → 25%
▲ 3 个百分点
首帧之前的工作
示例数据常见错误
- 用旗舰机连办公室 Wi-Fi 测试。 最慢的那 10% 用户,硬件和网络完全不同。
- 只看平均数。 用中位数和第 90 百分位;平均数会掩盖导致卸载的长尾。
- 启动时初始化所有 SDK。 第三方 SDK 是冷启动慢的常见原因。
- 性能只修一次。 不按版本跟踪,新代码会把问题带回来。
- 忽略按机型聚集的崩溃和 ANR。 一个机型系列可能占了大部分问题。
在 TapCub 里跟踪 App 性能
TapCub 的移动 SDK 会上报 App 启动,在平台支持的情况下也会上报崩溃和性能采样:
- 应用统计 › 质量与归因 › 稳定性 显示无崩溃用户占比、崩溃、ANR、界面卡顿,以及冷启动、热启动中位数和内存,错误分组可以标为已解决。
- 设备 按机型、系统版本、分辨率、网络拆分活跃用户,能看出问题是不是集中在某类设备上。
- 应用统计 › 用户分析 › 版本分布 显示每个版本的崩溃数,用来发现发版回退。见跟踪 App 版本和无崩溃率。
文档里有两点要注意:冷启动时间取自启动事件上的时长,SDK 适配没有设置时就是空的;帧率图需要打开性能采样。TapCub 是统计工具,不是性能剖析器:找具体是哪段代码拖慢了 App,要用 Android Studio 或 Xcode。
常见问题
移动 App 冷启动多快算好? 目标是中端机上中位数 2 秒以内。Android Vitals 认为 5 秒及以上的冷启动过长。
冷启动、温启动、热启动有什么区别? 冷启动是从零启动 App 进程;温启动复用进程,但重新创建 Activity 或页面;热启动是把还在内存里的 App 切回前台。
怎么找到是什么拖慢了 App? 先用线上数据找出慢的是哪个页面、版本或设备,再用剖析工具(Android Studio Profiler、Xcode Instruments)复现,找到对应的代码。
统计 SDK 会拖慢 App 吗? 任何在启动时初始化的 SDK 都会给首帧之前增加工作量。统计 SDK 要异步初始化,非必需的 SDK 放到首屏之后再初始化。
参考资料
- Android Developers:应用启动时间
- Android Developers:Android Vitals
- Apple Developer:缩短 App 的启动时间
- Android Developers:Baseline Profiles 概览
这篇文章对你有帮助吗?
我们会根据反馈修改和补充这篇内容。
提交没有成功,请稍后再试。
谢谢你的反馈,我们会据此改进这篇内容。你已经反馈过这篇了,谢谢。

