启动时间测量方法论:ADB、Systrace、自定义埋点
做性能优化,第一件事不是动手改代码。
而是搞清楚——你现在到底有多慢。
说白了,测量是优化的前提。没有数据,你连问题在哪都不知道。
我在早期做动态化项目时,就踩过这个坑。埋头优化了半天,结果发现测的数据根本不准,白忙活一场。从那时起,我养成了一个习惯:先建好度量体系,再动手优化。
这一章,我把最常用的三种启动时间测量方法整理出来。它们各有侧重,适合不同场景。
1. ADB 命令:最快拿到冷启动耗时
ADB(Android Debug Bridge)是安卓开发者最基础的调试工具。启动时间测量,用它就够了。
我常用的命令是这样的:
adb shell am start -W -n com.example.app/.MainActivity
执行后,终端会返回类似以下的信息:
Starting: Intent
Activity: com.example.app/.MainActivity
ThisTime: 350
TotalTime: 350
WaitTime: 365
几个关键字段说明一下:
- ThisTime:当前 Activity 的启动耗时(不含上一个 Activity 的销毁时间)
- TotalTime:整个启动链路的耗时,包含 Application 的 onCreate 等阶段
- WaitTime:从用户点击到界面可交互的完整时间
我个人更关注 TotalTime。它反映了从进程创建到页面首帧渲染的全过程。
adb shell am force-stop com.example.app
2. Systrace 与 Perfetto:找出瓶颈在哪
ADB 只能告诉你「多慢」。但如果你想搞清楚「为什么慢」,就得用 Systrace 或 Perfetto 了。
Systrace 是 Android 内置的 trace 工具。它能把系统层面、应用层面的耗时操作,按时间轴展开给你看。我现在更推荐用 Perfetto,它是 Systrace 的升级版,功能更强,UI 也更好用。
使用方法很简单:
# 启动 Perfetto 录制(需配置 trace 点)
python3 /path/to/perfetto/tools/record_android_trace \
-c /path/to/config.pbtx \
-o /path/to/output.trace
我个人习惯在应用启动时,加入以下自定义 trace 段:
Trace.beginSection("App.onCreate");
// 初始化逻辑
Trace.endSection();
Trace.beginSection("DynamicEngine.init");
// 引擎初始化
Trace.endSection();
在 Perfetto 的 UI 上,你能看到这些 trace 段的开始、结束、以及内部的子任务。有一次我就通过这种方式,发现某个 SDK 的初始化竟然占了 800ms,而我之前一直以为是网络加载慢。
3. 自定义埋点:精确到毫秒级的核心链路
ADB 和 Perfetto 都有一个问题:它们测的是「系统视角」的启动时间。但业务方关心的,往往是「用户视角」的时间——比如从点击图标到看到首页内容。
这时候,就需要在代码里埋点。
我的做法是,定义几个关键的里程碑:
- Application.onCreate 开始
- 动态化引擎初始化完成
- 首页请求发送
- 首页请求返回
- 首屏渲染完成
代码实现大致如下:
class StartupMonitor {
companion object {
private val milestones = mutableMapOf<String, Long>()
fun mark(name: String) {
milestones[name] = SystemClock.elapsedRealtime()
Log.d("StartupMonitor", "[$name] at ${milestones[name]}")
}
fun report() {
val sorted = milestones.entries.sortedBy { it.value }
sorted.forEachIndexed { index, entry ->
if (index > 0) {
val diff = entry.value - sorted[index - 1].value
Log.d("StartupMonitor", "${entry.key} took ${diff}ms")
}
}
}
}
}
然后在启动流程的各个节点调用 StartupMonitor.mark("xxx")。
我最推崇这种做法,因为它精确、可聚合、可对比。线上环境也能用,只要做好开关控制。
核心原则: 三种方法不是互斥的,而是互补的。
- 本地调试用 ADB 快速验证
- 排查性能瓶颈用 Perfetto
- 线上监控和对比用 自定义埋点
好了,这三种方法就介绍完了。ADB 用来快速摸底,Perfetto 用来追查根因,自定义埋点用来做长期监控。三者结合使用,你才能对启动时间有一个完整、准确的认知。
嗯,这里要再强调一句:测量本身也要注意精度。比如多次测量取中位数、排除异常值、保证测试环境一致。这些东西看起来很基础,但很多人都会忽略。