4. Systrace 基础录制:trace 标签选择、buffer 大小、录制时长、标记用户交互
在帧率抖动问题排查中,Systrace 是最核心的 CPU/GPU 调度可视化工具。录制参数配置不当(标签缺失、buffer 溢出、时长过长/过短、缺少用户交互标记)会直接导致 trace 无法反映真实抖动根因。本章聚焦数据采集前的参数决策与录制操作,确保每一份 trace 都能回答“抖动发生在哪个阶段”这一关键问题。
常见陷阱:许多开发者直接执行默认
systrace.py,不指定标签和 buffer,导致系统服务调度信息丢失,或 trace 在 5 秒后因 buffer 满而截断,错过关键抖动瞬间。
4.1 现象识别:什么样的 trace 是“有效”的?
- 标签完整:至少包含 sched、freq、gfx、view、input、am、dalvik 等关键分组。
- buffer 未溢出:trace 结束处不应出现
TRACE_BUFFER_FULL标记。 - 时长覆盖抖动区间:录制时长应比预期抖动周期长 3~5 秒。
- 用户交互有标记:触发抖动的操作(滑动、按钮点击)必须被独立标签圈选,便于后面快速定位。
4.2 数据采集:Systrace 录制参数决策矩阵
| 参数 | 推荐值 | 调试建议 | 常见错误 |
|---|---|---|---|
| 标签 (-t) | sched,freq,gfx,view,input,am,hidl,hal,res,load,dalvik |
GPU 相关抖动追加 gfx,hal,res;网络相关追加 net,wifi |
仅用默认 sched gfx view,缺少 freq / dalvik 无法定位 CPU 频率和 GC 挂起 |
| Buffer 大小 (-b) | 40960 (40 MB) 起,复杂场景用 81920 |
先跑 5 秒测试,结尾无溢出则增大 20% 更保险 | 使用默认 2048,高端设备 2 秒内 buffer 满,后段无数据 |
| 录制时长 (-t 秒) | 执行操作宽限期 + 抖动期 + 5秒缓冲 | 滑动/动画抖动:12秒;安转后冷启动:15秒 | 录制 30 秒以上导致文件巨大或 buffer 溢出,且后续分析困难 |
| 用户交互标记 | 使用 --from-file 或手动 echo 123 > /sys/.../trace_marker |
在预期抖动前 0.5 秒写入标记,方便在 trace 中快速定位 | 无标记,全凭肉眼在 10 秒内找抖动点,效率低易漏 |
4.3 录制步骤:带标记的 Systrace 采集命令
以下是以 Python 脚本方式调用 systrace(Android 10+ 推荐 ATrace 方式):
# 1. 定义标签(显式指定所有需要的分组)
TRACE_TAGS="sched freq gfx view input am dalvik"
# 2. 设置 buffer 大小(KB 单位)
BUFFER_SIZE=40960
# 3. 录制时长(秒)——配合预期操作窗口
DURATION=12
# 4. 启动录制(Android 10 以上用 perfetto 兼容层,仍可用 systrace.py)
python systrace.py --time=$DURATION \
--buf-size=$BUFFER_SIZE \
--atrace-categories=$TRACE_TAGS \
--link-to-sbrowser \
-o trace_output.html
# 5. 在另一个终端执行用户操作(如滑动、点击),并在关键点注入标记
# 假设操作脚本为 swipe.sh,内部在滑动前写入 trace_marker
adb shell "echo 'B|app|START_SWIPE' > /sys/kernel/debug/tracing/trace_marker"
# 执行滑动动作...
adb shell "echo 'E|app|START_SWIPE' > /sys/kernel/debug/tracing/trace_marker"
标记注入说明:使用 B|app|LABEL 开始一个阶段,E|app|LABEL 结束,LABEL 需全局唯一。在 Chrome DevTools 的 Performance 面板中,这些标记会自动显示为与 app 同名的色条。
技巧:对于复杂交互(如连续滑动 3 次),可在每次滑动前插入序号标记
SWIPE_1、SWIPE_2、SWIPE_3,方便在 trace 中对比每次滑动的帧时长差异。
4.4 原因定位:从 trace 中快速找到标记区间
录制完成后,打开生成的 HTML trace 文件。使用快捷键 m 搜索标记名称(如 START_SWIPE)。系统会自动高亮该时间段,直接放大到该窗口,观察 vsync、SurfaceFlinger、GPU completion 等关键事件的分布密度。
- 如果标记区间内出现连续 丢帧(Missed vsync) 或 长块调度停顿,说明问题集中在该操作。
- 若标记前后都有抖动,说明操作本身触发后遗效应(如 GC 或 layout 递归)。
- 若整个 trace 中无标记对应的色块,检查是否成功写入
trace_marker(需 root 或 userdebug 版本)。
4.5 修复动作:调整参数重录直到 trace 完整
| 观察到的问题 | 修复动作 |
|---|---|
trace 尾部出现 TRACE_BUFFER_FULL |
增大 buffer 至 81920 或缩短录制时长至 8 秒 |
| 标记区间内无数据(空白) | 降低 buffer 至 20480 或追加 sched / freq 标签 |
| 未找到用户交互标记 | 确认手机版本支持 trace_marker,或改用 am trace-ipc 方式标记 |
| trace 文件大于 500MB,加载卡顿 | 缩短时长,仅录制抖动窗口前后 3 秒;或使用 perfetto 的 strip 功能 |
4.6 复测:验证参数调整后的 trace 质量
重复执行步骤 4.3,但只录制 5 秒(轻量测试),观察:
- buffer 使用率是否 < 90%(在 trace header 中查看)
- 标记是否清晰可见
- 关键调度事件(如频率切换、binder 调用)是否出现在预期位置
如果以上都通过,再恢复至正式录制时长进行完整采集。
4.7 预防:建立录制规范模板
团队录制 checklist(可在 CI 中集成):
- 录制前确认设备已连接 Wi-Fi / USB,电池 > 80%
- 预热场景:先执行一次无记录操作以消除 JIT 预热
- 固定标签组:每个项目维护一个
systrace_tags.txt,含备选开关 - 标记命名规范:
B|app|{TEST_CASE}_{SEQUENCE},如B|app|LIST_SCROLL_03 - 录制后自动校验 buffer 溢出:解析 trace 开头,若有 warning 则标记失败
使用上述流程,每次录制都会生成一份包含显式用户交互标记、buffer 未溢出、标签完整的 Systrace 文件。下一阶段(第 5 章)将基于这份高质量 trace 进行帧率抖动根因定位。