性能分析工具链:systrace、perfetto、simpleperf、top、vmstat 等工具使用入门
做 AOSP 性能优化,最怕的不是不会写代码,而是出了问题不知道从哪下手。说实话,我刚入行那会儿,遇到系统卡顿、掉帧,第一反应就是去翻 logcat,结果翻半天也看不出所以然。后来团队里一位老大哥跟我说了一句话我记到现在:“没有数据,就没有优化。”
说白了,分析工具就是你的眼睛。这一章我把团队里最常用的几把“瑞士军刀”梳理一遍,每个工具怎么用、什么时候用、有什么坑,我都用自己的经历给你讲透。
核心观点:定位性能瓶颈,先得学会“看”。systrace 看宏观调度,perfetto 看精细事件,simpleperf 看 CPU 热点,top/vmstat 看系统负载。组合使用,才是高手。
1. top & vmstat——最朴素的侦察兵
我习惯在排查问题的第一分钟就跑 top 和 vmstat。为什么?因为它们不需要任何配置,直接就能告诉你系统当前是不是“生病了”。
$ adb shell top -n 1 -d 1
$ adb shell vmstat 1 5
top 看 CPU 占用最高的进程,vmstat 关注 runnable 队列长度和 swap 交换。如果 r 列长期大于 CPU 核数,说明系统过载;如果 si/so 频繁非零,内存该加或者泄露了。
我曾经在一台低端设备上发现掉帧,top 看不出哪个进程异常,但 vmstat 显示 r 一直是 16(才 4 核),赶紧打开 ps -T 才发现是某个 Native 线程死循环了。要是没有 vmstat,我可能还在怀疑 GPU 驱动。
2. systrace——老牌调度分析神器
如果说 top 是听诊器,那 systrace 就是 X 光机。它基于 ftrace,能记录内核调度、Binder 通信、SurfaceFlinger 合成等关键事件。
$ adb shell atrace --async_start
# 复现问题(比如滑动几下)
$ adb shell atrace --async_dump > /data/local/tmp/trace.systrace
$ adb pull /data/local/tmp/trace.systrace
# 然后拖到 chrome://tracing 里看
用 systrace 主要看三样:CPU 时间线里有没有大段空白;Binder 同步卡在哪个 service;Vsync 信号是否准时。我记得有一次排查微信卡顿,systrace 里清晰看到 SurfaceFlinger 在等一个 Binder 回复超时了 8ms,最后定位到是 ContentProvider 的数据库锁——这种问题靠 logcat 根本看不出来。
注意:systrace 在 Android 12 之后逐步被 perfetto 替代,但老版本设备仍然常用。而且 trace 文件很占空间,别长时间开着。
3. perfetto——新一代全栈追踪器
perfetto 可以理解为 systrace 的升级版。它支持更多探针,比如 heapprofd 做 Native 内存分析,perf profiler 做 CPU 采样。配置是用 protobuf 写的,威力很大。
$ adb shell perfetto -c /data/misc/perfetto.config --txt -o /sdcard/trace.perfetto-trace
# 示例配置(一段 text proto):
duration_ms: 10000
buffers: { size_kb: 65536 }
data_sources: {
config { name: "linux.ftrace" ftrace_config { ftrace_events: "sched/sched_switch" } }
}
data_sources: {
config { name: "linux.process_stats" }
}
我一般用 perfetto 结合 sqlite 分析。比如跑完 trace 后在 ui.perfetto.dev 上直接写 SQL 查询:哪段时间 CPU 使用率超过 80%,哪个线程叫醒最频繁。这比肉眼翻时间线有效率多了。
4. simpleperf——CPU 热点狙击手
当你通过上面的工具锁定了某个进程/线程,但不知道代码哪里慢,就得请出 simpleperf。它基于 perf_event_open,能做精确的采样。
$ adb shell simpleperf record --call-graph fp -p $(pidof com.android.systemui) --duration 10 -o /sdcard/perf.data
$ adb shell simpleperf report --input /sdcard/perf.data --symbols | head -20
这里要注意:--call-graph fp 需要编译时开启 -fno-omit-frame-pointer,否则调用链会断掉。我踩过这个坑——第一次跑出来全是问号,白忙一场。
simpleperf 还能生成火焰图:
$ adb shell simpleperf report --input perf.data --full-callgraph > /tmp/report.txt
# 在 PC 上用 FlameGraph 工具 svg 化
| 工具 | 适用场景 | 输出形式 | 学习成本 |
|---|---|---|---|
| top | 快速看系统是否过载 | 文本 | ★☆☆☆☆ |
| vmstat | 内存/CPU 队列瓶颈 | 文本 | ★☆☆☆☆ |
| systrace | 调度、同步、Binder 问题 | HTML 时间线 | ★★★☆☆ |
| perfetto | 全栈 Trace + SQL 分析 | proto / 网页 | ★★★★☆ |
| simpleperf | CPU 热点、火焰图 | 文本 / SVG | ★★★☆☆ |
避坑指南——我用真金白银换来的教训
- 忘了关 trace 导致 flash 写坏:我曾经在开发板上开 systrace 跑了两小时,结果 /data 分区写爆,设备变砖。现在我会在配置里加
max_file_size和buffer_size限制。 - 采样频率太高把系统拖死:simpleperf 的
-f 1000(1KHz)在低端设备上本身就会带来 20% 的 CPU 开销。我建议先-f 400试跑,如果现象还能复现就够了。 - perfetto 配置写错不报错:它不会检查配置里的 data_source 名字拼写。如果发现 trace 文件很小,先确认
cat /data/misc/perfetto-traces/trace里有没有错误日志。 - 忽略权限:某些工具需要 root 或 system_app 才能获取所有内核事件。如果非 root 设备,用
profiling权限或者 adb 授权(参考官方文档)。
工具这种东西,光看不管用。我建议你今晚就试着跑一下 top 和 simpleperf,看看自己手机上最占 CPU 的是谁。等你真正用出感觉,你就会发现——性能优化的第一步,其实就是拿起对的工具。嗯,就这么简单。