第2章 移动端基准测试目标:冷启动、热启动、页面加载、内存基线
移动端基准测试的目标是建立可重复、可对比的性能基线,用于捕捉性能退化、验证优化效果。本章定义四个核心测试场景:冷启动、热启动、页面加载和内存基线。每个场景都有明确的触发条件、测量指标和采集工具。理解这些目标的差异,是后续压测实施和CI集成的基石。
2.1 冷启动基准测试
原理:冷启动指进程被系统完全杀死后,用户首次点击应用图标到首屏内容完全绘制完成的过程。此阶段包括进程创建、主线程初始化、类加载、Application 和 Activity 生命周期、布局 inflate 等环节,对用户体验影响最大。
实现流程
- 确保应用进程未运行:
adb shell am force-stop <package> - 清除系统缓存(可选):
adb shell pm clear <package>(仅可用于首次启动测试,后续采集需谨慎,避免破坏持久化状态) - 启动应用并记录启动完成事件:
adb shell am start -W <package>/.<Activity> - 解析输出的
ThisTime、TotalTime、WaitTime,取多次测量中位数或P95。
关键指标:TotalTime(从进程创建到首帧渲染完毕的时间,单位毫秒),行业参考:冷启动应 < 2s(中端设备),< 1.5s(旗舰设备)。
常用命令与自动化脚本示例
# 冷启动单次测量
adb shell am force-stop com.example.app
adb shell am start -W com.example.app/.MainActivity | grep TotalTime
# 批量采集 10 次(需要 sleep 间隔,避免系统重排)
for i in $(seq 1 10); do
adb shell am force-stop com.example.app
sleep 2
adb shell am start -W com.example.app/.MainActivity | grep TotalTime >> cold_start.txt
done
2.2 热启动基准测试
原理:热启动指应用进程已在后台存活(未被系统杀死),用户重新从桌面切换回应用时的启动体验。应用对象保留在内存中,主要开销为 Activity 重建(onCreate/onStart/onResume),无需重新初始化整个进程和 Application。热启动时间通常只有冷启动的 1/3~1/2。
实现流程
- 先让应用完全冷启动一次,进入待测试页面。
- 模拟 Home 键切后台:
adb shell input keyevent KEYCODE_HOME - 等待 1~2s 后,重新启动目标 Activity:
adb shell am start -W <package>/.<Activity> - 记录
TotalTime,注意与冷启动差异:热启动的TotalTime应远小于冷启动,否则可能发生了进程被系统回收(实质仍是冷启动)。
验证进程是否存活:用 adb shell ps | grep <package> 检查,若不存在则视为冷启动,需剔除。
典型热启动指标:热启动 < 700ms(中端设备),< 400ms(旗舰设备)。
2.3 页面加载基准测试
原理:页面加载测试聚焦于应用内部次级页面(非首屏)的打开性能,例如电商App的商品详情页、Feed列表页的滑动加载。测试通过自定义 Activity 曝光回调或自动化工具(如 Espresso、UI Automator)触发页面跳转,并收集 firstPaint、firstContentfulPaint、onNextDraw 等前端感知指标。
实现流程
- 定义页面加载结束标志:通常使用
ViewTreeObserver.OnDrawListener或ReportFullyDrawn()API。 - 在测试环境中,使用
adb shell am start -W配合特定 Intent 跳转到子页面。 - 对于列表页的滚动加载(如 RecyclerView),需记录 首帧完成时间 和 列表第一次充满屏幕时间。
采集命令示例(子页面跳转)
# 假设商品详情页 Activity 为 .ProductDetailActivity,需传入商品 ID
adb shell am start -W com.example.app/.ProductDetailActivity \
--es "product_id" "12345" | grep TotalTime
注意事项:页面加载测试强烈依赖网络状态(若页面有网络请求),应在控制网络延迟(如使用弱网模拟工具)或缓存数据的条件下测试。建议区分首次加载(无缓存)和二次加载(缓存命中)。
2.4 内存基线测试
原理:内存基线测试旨在量化应用在不同场景下的PSS(Proportional Set Size)、Java Heap、Native Heap 和 Graphics 等内存使用分布。目标有两个:一是确认应用在承受压力前的内存基线值;二是发现内存泄漏或异常增长。
关键工具与命令
adb shell dumpsys meminfo <package>—— 获取当前进程的内存快照。/proc/meminfo结合/proc/<pid>/status可以细粒度分析。- 自动化推荐使用
adb shell top或dumpsys gfxinfo配合脚本循环采集。
典型场景与基线脚本示例
# 在页面加载完成后采集内存快照
adb shell dumpsys meminfo com.example.app | grep "TOTAL" >> mem_base.txt
# 循环 30 秒,每秒采集一次(用于检测泄漏)
for i in $(seq 1 30); do
adb shell dumpsys meminfo com.example.app | grep "TOTAL PSS" | awk '{print $3}' >> pss_series.txt
sleep 1
done
基线判定:取多次测量中位数作为基线值。若某次采集的 PSS 高于基线 + 20% 且持续不回落,应视为内存异常,需触发告警。
adb shell dumpsys meminfo -s(简略模式)以保证跨设备可比性。若使用 procrank 等工具,需确保设备已 root。
2.5 四个基准测试目标对比
| 测试目标 | 触发条件 | 核心指标 | 典型工具/命令 | 建议采集次数 |
|---|---|---|---|---|
| 冷启动 | 进程完全不存在 | TotalTime (ms) | am start -W + force-stop |
≥ 10 次 |
| 热启动 | 进程存活,重新前台 | TotalTime (ms) | am start -W 在后台后执行 |
≥ 8 次 |
| 页面加载 | 内部页面首次跳转 | TotalTime / firstPaint (ms) | am start -W + Intent / ReportFullyDrawn() |
≥ 5 次(区分缓存状态) |
| 内存基线 | 稳定场景下的内存快照 | PSS (kB)、Java Heap (kB) | dumpsys meminfo / procrank |
≥ 10 次(每场景) |
2.6 基准测试总体流程(内联SVG)
图中展示了从准备设备到最终 CI 告警的完整链路。实际执行时,冷启动、热启动和页面加载测试可以并行或按序执行,但内存基线测试必须至少在每种场景稳定后采集,以保证基线代表真实运行状态。