2. 热启动与温启动耗时对比测量
为什么热启动、温启动、冷启动的耗时不能直接比较
冷启动从进程不存在开始,包含进程创建、Application 初始化、Activity 创建与首帧渲染;热启动时进程与 Activity 对象都还在,系统只需把已有任务栈重新切到前台;温启动介于两者之间——进程仍存活,但 Activity 已被销毁,需要重新执行 Activity 创建与首帧渲染。三者起点不同,因此对比时必须先固定“起点定义”,否则测出来的差值没有意义。
构造三种场景的操作要点
测量前先确认设备处于稳定状态,避免后台任务、系统更新或低电量模式干扰。以下操作在真机或模拟器上均可执行,关键是每次测量前把应用恢复到对应状态。
- 冷启动:在系统设置中强制停止应用,或执行
adb shell am force-stop 包名,确认进程已不存在后再点击图标启动。 - 温启动:先正常启动应用,按返回键退出到桌面(Activity 被销毁但进程保留),再重新点击图标。可用
adb shell dumpsys activity processes | grep 包名确认进程仍在。 - 热启动:启动应用后按 Home 键回到桌面(Activity 进入后台但未销毁),再点击图标恢复。此时进程与 Activity 对象都存活。
adb shell ps | grep 包名 是否有输出;判断 Activity 是否存活,可观察 adb shell dumpsys activity activities 中该 Activity 是否仍处于 RESUMED 或 PAUSED 状态。用 am start 的 -W 参数采集耗时
Android 提供了 am start -W 命令,可以输出本次启动的 TotalTime、WaitTime 等指标。它测量的是从 am 命令发出到 Activity 首帧显示的时间,适合快速对比三种场景。示例命令:
# 冷启动:先强制停止,再启动
adb shell am force-stop com.example.app
adb shell am start -W -n com.example.app/.MainActivity
# 温启动:启动后按返回键退出,再启动
adb shell input keyevent KEYCODE_BACK
adb shell am start -W -n com.example.app/.MainActivity
# 热启动:启动后按 Home 键,再启动
adb shell input keyevent KEYCODE_HOME
adb shell am start -W -n com.example.app/.MainActivity
每次执行后记录输出中的 TotalTime。建议每种场景连续测量 5 次,去掉第一次(可能受系统缓存影响),取后 4 次的平均值作为该场景的耗时。示例记录如下(数值为教学示例,非真实设备实测):
| 场景 | 第1次 | 第2次 | 第3次 | 第4次 | 第5次 | 平均(后4次) |
|---|---|---|---|---|---|---|
| 冷启动 | 820 ms | 790 ms | 805 ms | 795 ms | 800 ms | 797.5 ms |
| 温启动 | 410 ms | 395 ms | 400 ms | 390 ms | 405 ms | 397.5 ms |
| 热启动 | 120 ms | 110 ms | 115 ms | 108 ms | 112 ms | 111.25 ms |
结果判读与影响边界
从示例数据可以看到:温启动比冷启动快约 400 ms,这部分差值主要来自省去的进程创建与 Application 初始化;热启动又比温启动快约 286 ms,这部分来自省去的 Activity 创建与布局加载。这说明进程存活状态对启动耗时的影响集中在 Application 初始化阶段,而 Activity 是否存活则影响 Activity 创建与首帧渲染阶段。
需要特别注意:如果 Application 初始化本身很轻,冷启动与温启动的差距会缩小;如果 Activity 布局复杂,温启动与热启动的差距会拉大。因此不能脱离具体应用谈“热启动一定比温启动快多少”,而应把三种场景的耗时作为一组基线,后续优化时分别观察各阶段的变化。
am start -W 测量时,如果应用有启动页或广告页,TotalTime 可能只统计到第一个 Activity 显示,不代表用户真正看到主界面的时间。此时应结合 adb shell am start -W 的 ThisTime 与自定义埋点综合判断。可复用的测量记录表
把每次测量的原始数据填入下表,便于后续对比优化效果。字段可根据实际需要增减。
| 日期 | 设备/系统 | 场景 | TotalTime 原始值(ms) | 后4次平均(ms) | 备注 |
|---|---|---|---|---|---|
| 示例 | Pixel 6 / Android 14 | 冷启动 | 820, 790, 805, 795, 800 | 797.5 | 首次测量前已 force-stop |
| 示例 | Pixel 6 / Android 14 | 温启动 | 410, 395, 400, 390, 405 | 397.5 | 返回键退出后进程仍存活 |
| 示例 | Pixel 6 / Android 14 | 热启动 | 120, 110, 115, 108, 112 | 111.25 | Home 键后 Activity 未销毁 |
完成记录后,用“冷启动平均 − 温启动平均”得到进程与 Application 初始化的代价,用“温启动平均 − 热启动平均”得到 Activity 创建与首帧渲染的代价。这两个差值就是后续优化时最值得关注的边界。