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 则标记失败
Systrace 录制参数选择与标记注入流程 Systrace 录制参数选择与标记注入流程 选择标签 sched,gfx,view,input... 设定 Buffer ≥ 40960 KB 设定时长 12~15 秒 注入用户交互标记 trace_marker B|app|LABEL 录制进行中插入标记 停止 & 导出 trace_output.html 校验 trace 完整性 检查 buffer / 标记是否可见 参数调整重录 确保标记与操作 同步误差<0.5s

使用上述流程,每次录制都会生成一份包含显式用户交互标记、buffer 未溢出、标签完整的 Systrace 文件。下一阶段(第 5 章)将基于这份高质量 trace 进行帧率抖动根因定位。