Trace工具全景:Systrace、Perfetto、Traceview、SimplePerf、atrace 的适用场景

做冷启动优化这些年,我摸过的Trace工具一只手数不过来。每个工具都有自己的脾气,选对了事半功倍,选错了…嗯,你懂的。今天我就把这五个家伙的底细给你掰扯清楚。

核心原则:没有最好的Trace工具,只有最合适的场景。先搞清楚你想看什么——是系统调度?是函数耗时?还是CPU采样?再下手。

Trace工具全景:分层与场景 系统级追踪 应用级性能分析 Systrace 系统调度 / 主线程卡顿 SurfaceFlinger / Binder Perfetto 系统级精细追踪 内核/内存/GPU atrace 命令行轻量采集 Systrace的后端引擎 Traceview 方法级耗时分析 开销较大,适合脱机 SimplePerf CPU采样 / 热点定位 Native / 混合调用

1. Systrace —— 老牌系统级大杀器

Systrace是我最早接触的Trace工具,那时候Android还叫Froyo。它本质上是对内核ftrace的封装,能抓取系统调度、SurfaceFlinger、Binder等上百个事件。

适用场景:

  • 冷启动中主线程到底被谁抢占了CPU?——Systrace一目了然
  • 掉帧、卡顿、ANR的前期排查
  • 从用户体验层面看「看起来慢在哪里」

我的一点经验:抓Systrace时记得带长时长参数 --time=10,避免漏掉关键帧。另外建议带上 -a 包名,只关注目标App。

注意:Systrace在新版Android中已被Perfetto替代,但旧版项目还是要会用的。

2. Perfetto —— 新一代全能选手

Perfetto是Google近年主推的Trace工具,我前年开始全面转用它。说实话,Systrace能做的它都能做,做不到的它也能做。

适用场景:

  • 需要查看内核调度、内存分配、GPU渲染等系统级细节
  • 长时间持续追踪(支持数十分钟)
  • 跨进程、跨系统边界的问题(如I/O瓶颈)

我个人习惯直接在浏览器里用 ui.perfetto.dev 打开trace文件,交互非常顺畅。而且它支持SQL查询,你可以写自定义查询定位极端case。

3. atrace —— 命令行的幕后英雄

很多人不知道atrace其实是Systrace和Perfetto底层的命令行工具。它的优势是轻量、可脚本化。

适用场景:

  • 在CI或自动化测试中集成Trace采集
  • 设备无界面,只能adb连的时候
  • 只想快速抓取某个tag(比如gfx、input)
# 抓取10秒的图形和输入事件
adb shell atrace --async_start -c -t 10 gfx input
# ... 执行操作 ...
adb shell atrace --async_dump > /tmp/my_trace.atrace

避坑指南:我曾经在线上设备用过atrace连续采集,结果发现buffer写满了丢数据。后来加上了 --buffer_size 16384 才解决。默认buffer只有8K,根本不够用。

4. Traceview —— 方法级别的慢镜头

如果你已经知道问题在哪个线程,想看每个方法的执行耗时——Traceview最合适。但注意,它的运行时开销很大,不建议在生产环境用。

适用场景:

  • 定位某个具体函数的内部耗时分布
  • 对比优化前后方法耗时变化
  • 分析冷启动中「onCreate -> onResume」每个步骤的耗时占比

你想想看,有时候系统Trace显示主线程空闲,但启动就很慢。这时候用Traceview一抓,发现某个方法里调了三次SharedPreference的commit(),每个都等I/O。这就是它的价值。

5. SimplePerf —— Native与CPU的显微镜

当问题涉及到Native代码、JNI调用或者CPU热点,Traceview就无能为力了。SimplePerf是Android官方的CPU采样工具,基于perf_event,开销极低。

适用场景:

  • 定位Native crash的调用栈黑盒
  • 找到哪段C++代码吃掉了最多的CPU时间
  • 与Systrace配合,先看调度再看热点
# 采样3秒,记录调用频率
adb shell simpleperf record -p <PID> --duration 3 -o /data/local/tmp/perf.data
adb shell simpleperf report -i /data/local/tmp/perf.data

我的实战案例:之前有个冷启动慢在so加载阶段,Systrace只显示Binder忙,查不出原因。我用SimplePerf一采,发现有个native函数在while循环里做了大量字符串拼接——原来是业务方在JNI里用了低效的std::string操作。

工具选择速查表

工具 关注层级 开销 典型冷启动场景
Systrace 系统级(线程、进程、图形) 中 主线程调度、掉帧
Perfetto 系统级+内核级 低~中 长时间追踪、多维度分析
atrace 系统级(轻量) 低 自动化测试、快速抓取
Traceview 应用方法级 高 方法内耗时、代码级优化
SimplePerf Native/CPU级 极低 Native热点、JNI性能

看到这里你应该明白了——这几个工具不是互斥的,而是互补的。我个人的工作流程通常是:先用Perfetto或Systrace抓全貌,发现可疑区域后用Traceview或SimplePerf下钻。至于atrace,我喜欢用脚本把它包在自动化流程里,省事又可靠。

一句话总结:系统问题找Perfetto(或Systrace),方法问题找Traceview,Native问题找SimplePerf,自动化场景找atrace。工具在手,心里不慌。