6、Systrace基础:Systrace原理、抓取方法、时间轴解读、关键指标
说到Android性能调试,Systrace是我最常用的工具之一。它就像系统的“心电图”,能让你一眼看出哪里卡了、哪里慢了。我刚开始接触Android系统时,面对一堆log完全摸不着头脑,直到学会了Systrace——嗯,那感觉就像打开了新世界的大门。
6.1 Systrace到底是什么?
说白了,Systrace是一个轻量级的性能分析工具。它不直接告诉你“这里慢了”,而是把系统里各个模块在做什么、花了多长时间,全部画在一条时间轴上。你一看就知道:哦,原来是这个线程在等那个线程,导致界面卡了。
它的核心原理其实不复杂:
- 打点机制:系统关键路径上预埋了trace点(比如开始绘制、开始布局)
- 内核ftrace:利用Linux内核的ftrace框架收集调度信息
- 用户态atrace:收集App和Framework层的trace事件
- 时间同步:所有事件都带时间戳,精确到微秒级
关键点:Systrace的开销非常小,生产环境也能用。我在线上问题排查时经常直接抓,基本不影响用户体验。
6.2 怎么抓Systrace?
抓取方法有好几种,我根据场景不同会换着用。这里给你总结最实用的三种:
方法一:命令行抓取(我最常用的)
适合开发机、自动化脚本。我个人习惯用这个,因为可控性最强。
# 基本抓取,持续5秒
python systrace.py -t 5
# 抓取特定模块,比如只看GPU和输入
python systrace.py -t 5 gfx input view
# 抓取所有模块,输出到文件
python systrace.py -t 10 -o mytrace.html
# 常用模块列表
# gfx - 图形渲染
# input - 输入事件
# view - View绘制
# wm - 窗口管理
# am - Activity管理
# sched - CPU调度
# freq - CPU频率变化
我的小技巧:抓取时间别太长,5-10秒足够。太长的话文件巨大,打开都费劲。我一般先抓5秒,发现问题再针对性加长时间。
方法二:手机端直接抓(适合现场问题)
有时候问题复现条件苛刻,来不及连电脑。这时候用开发者选项里的“系统跟踪”最方便。
# 设置要跟踪的类别(在开发者选项里配置)
# 然后下拉通知栏,点击“系统跟踪”图标
# 开始 -> 复现问题 -> 停止
# 生成的trace文件在:
# /data/local/traces/
# 或者直接分享出来
方法三:代码中动态控制(适合自动化测试)
我在做自动化性能测试时,会在关键步骤前后用代码控制trace开关。
// 开始跟踪
adb shell atrace --async_start -c -b 16000 gfx input view sched freq
// 执行测试操作...
// 停止跟踪并保存
adb shell atrace --async_stop -z > /sdcard/trace_output
// 拉取到电脑
adb pull /sdcard/trace_output ./mytrace.html
注意:buffer大小(-b参数)默认是2048KB,如果抓取时间长或模块多,建议设大一点,比如16000。我曾经因为buffer太小,抓到的trace不完整,排查了半天才发现是数据被截断了。
6.3 时间轴怎么看?
打开生成的trace.html,你会看到一条长长的彩色时间轴。第一次看可能会觉得眼花,但别慌,我教你几个关键点:
界面布局
| 区域 | 说明 |
|---|---|
| 顶部时间轴 | 显示总时长,可以缩放、拖动 |
| 左侧进程/线程列表 | 每个进程可以展开,看到里面的线程 |
| 中间彩色条带 | 每个线程的活动,颜色代表不同事件类型 |
| 底部详情区 | 点击某个事件,显示详细信息 |
颜色含义
- 绿色:正常运行,通常表示等待或空闲
- 橙色:可运行但未运行(等待CPU)
- 红色:正在运行(占用CPU)
- 紫色:睡眠/阻塞(等锁、等IO)
- 蓝色:中断处理
核心技巧:看卡顿问题,重点关注“橙色”和“紫色”区域。橙色说明CPU不够用,紫色说明在等资源。我遇到过很多次,界面卡了,一看时间轴,主线程一大片紫色——原来是等一个锁等了200ms。
6.4 关键指标怎么看?
抓到了trace,也看懂了时间轴,接下来要关注几个核心指标。这些是我在实际项目中总结出来的“必看项”:
指标一:帧率(FPS)
在trace里按“F”键,会显示每一帧的绘制情况。重点关注:
- 掉帧:两帧间隔超过16.6ms(60fps)或8.3ms(120fps)
- jank:连续多帧掉帧,通常意味着有耗时操作
- 帧边界:绿色竖线表示vsync信号,如果绘制没在vsync前完成,就会掉帧
指标二:CPU调度延迟
看线程的“Running”状态是否连续。如果线程频繁在“Runnable”和“Running”之间切换,说明CPU调度有问题。
# 在trace中搜索你的线程名
# 看它的调度情况:
# - 连续红色:正常执行
# - 红橙交替:被频繁抢占
# - 大片橙色:CPU不够用,在排队
指标三:锁竞争
在trace里,锁等待会显示为紫色块,并且会标注“waiting for lock”。我建议重点关注:
- 主线程等锁:这是大忌,直接导致界面卡顿
- 锁持有时间:点开紫色块,看“Duration”字段,超过10ms就要警惕
- 锁链:有时候A等B,B等C,形成死锁链
避坑指南:我曾经排查过一个诡异问题——手机滑动时偶尔卡一下,但抓trace又抓不到。后来发现是抓取时机不对。我改成在卡顿发生前就开始抓,终于抓到一次:原来是某个后台线程在持有锁做数据库操作,主线程刚好要拿同一个锁。解决方案很简单,把数据库操作放到异步线程,或者用读写锁分离。
指标四:Binder调用
跨进程通信在trace里会显示为“Binder transaction”。关注点:
- 调用频率:短时间内大量Binder调用,说明设计不合理
- 调用耗时:点开看“Duration”,超过5ms就要优化
- 调用链:看是谁调了谁,有时候是A调B,B又调C,形成长链
6.5 实战:一个卡顿问题的排查思路
假设你遇到一个场景:App列表滑动时偶尔卡顿。我会这样用Systrace排查:
- 抓trace:用命令行抓10秒,包含gfx、input、view、sched模块
- 定位卡顿帧:按F键,找到掉帧的那一帧
- 看主线程:点击掉帧区域,看主线程在做什么
- 看耗时操作:如果主线程有长条红色,点开看是什么函数
- 看锁等待:如果有紫色块,看等的是哪把锁
- 看CPU调度:如果主线程是橙色,看其他核在做什么
记住:Systrace不是万能的,但它能帮你快速缩小问题范围。我一般先用Systrace定位到“是什么在耗时”,然后再用其他工具(比如perf、simpleperf)深入分析。
嗯,Systrace的基础就这些。你想想看,其实核心就是:抓对数据、看懂时间轴、关注关键指标。多练几次,你也能一眼看出系统瓶颈在哪里。