第3章 录制卡顿Trace的三种方式与参数选择规则
卡顿排查的第一步是获取高质量的Trace数据。本章围绕“数据采集”阶段,系统讲解命令录制、代码插桩、系统跟踪三种方式及其参数选择规则。你将在实际定位卡顿时,根据问题场景快速选定正确的录制方案。
三种录制方式总览
| 方式 | 核心原理 | 适用场景 | 优势 | 限制 |
|---|---|---|---|---|
| 命令录制 | 通过adb/perfetto命令触发一次性的Trace采集 | 线上/测试环境临时抓取;快速复现卡顿 | 无需代码改动,即刻使用 | 依赖终端操作;无法自定义高级触发条件 |
| 代码插桩 | 在应用源码中嵌入Perfetto SDK,按特定逻辑启动/停止Trace | 自动触发埋点;精准采集用户操作路径 | 可定制触发时机;可附带自定义标签 | 需要集成SDK,增加包体积 |
| 系统跟踪 | 通过系统服务(如long trace)或开发者选项持续采集 | 系统级卡顿分析;多进程交互问题 | 覆盖所有进程;支持超长录制 | 文件体积大;需root或debug构建 |
方式一:命令录制
命令录制是最灵活的临场式采集方式。典型流程:连接设备 → 设置ATRACE标签 → 执行perfetto命令 → 复现问题 → 停止并拉取Trace。
基础命令模板
adb shell perfetto \
-o /data/misc/perfetto-traces/card_issue.pb \
-t 10s \
-b 32mb \
sched freq idle am wm gfx view input
参数含义
- -o:输出路径(必须写入可写分区,建议/data/misc/perfetto-traces/)
- -t:持续时长,卡顿场景建议10~30秒
- -b:缓冲区大小,复杂场景推荐32~64 MB
- 末尾为数据源,卡顿分析必须包含:
sched(调度)、gfx(图形)、view(视图)、input(输入)
典型卡顿采集命令
adb shell perfetto \
-o /data/misc/perfetto-traces/jank_test.pb \
-t 15s \
-b 64mb \
sched freq idle am wm gfx view input
经验法则:线上设备若无法root,使用debug版本或通过
adb shell atrace降级采集(功能受限)。优先使用perfetto命令,数据更完整。
方式二:代码插桩
在应用关键路径(如点击响应、列表滑动、动画开始/结束)中嵌入Perfetto SDK的Trace开始/结束调用,实现“按需录制”。
集成要点
// 引入Perfetto SDK
#include "perfetto/tracing.h"
// 定义类别
PERFETTO_DEFINE_CATEGORIES(
perfetto::Category("app.jank")
.SetDescription("应用卡顿相关事件"),
perfetto::Category("app.network")
.SetDescription("网络请求"));
// 在需要录制的代码段中
TRACE_EVENT("app.jank", "UserClick", "button_id", buttonId);
// ... 实际业务逻辑 ...
TRACE_EVENT_END("app.jank");
参数选择规则
在代码中设置录制时长、缓冲区、数据源时,建议通过远程配置下发,避免硬编码:
// 动态启动Trace
perfetto::Tracing::Begin(
perfetto::TraceConfig cfg;
cfg.set_duration_ms(10000);
cfg.add_buffers()->set_size_kb(32768);
auto* ds = cfg.add_data_sources();
ds->mutable_config()->set_name("track_event");
// 可选:只采集当前进程
ds->mutable_config()->set_target_buffer(0);
// 开始录制
TracingSession::Setup(cfg);
);
注意:插桩录制会引入额外的trace overhead。生产环境务必限制单次录制时长≤30秒,缓冲区≤64 MB,并使用开关量控制录制启动。
方式三:系统跟踪
系统跟踪用于排查无法在单一应用内复现的卡顿(如后台服务抢占、SystemUI响应延迟)。通过perfetto --background或开发者选项中的“系统跟踪”开启持续录制。
启动命令(后台模式)
adb shell perfetto \
--background \
-o /data/misc/perfetto-traces/long_trace.pb \
-c /data/local/tmp/long_trace.cfg
配置文件示例(long_trace.cfg)
duration_ms: 300000 # 5分钟
buffers {
size_kb: 65536
fill_policy: RING_BUFFER
}
data_sources {
config {
name: "linux.syscalls"
}
}
data_sources {
config {
name: "android.surfaceflinger.frametimeline"
}
}
data_sources {
config {
name: "android.app.packages"
target_buffer: 0
}
}
# 只针对系统关键进程,减少体积
incremental_state_config {
clear_period_ms: 5000
}
适用判断:当卡顿发生在系统动画(如通知栏下拉、多任务切换)或多个应用交替阻塞时,优先使用系统跟踪,配置RING_BUFFER以避免磁盘爆满。
录制参数选择规则
| 场景特征 | 推荐方式 | 缓冲区 | 时长 | 关键数据源 |
|---|---|---|---|---|
| 应用内滑动/点击瞬间卡顿 | 命令录制 | 32 MB | 15 s | gfx, view, input, sched |
| 首帧渲染慢/启动黑屏 | 代码插桩(在Application.onCreate中启动) | 64 MB | 20 s | gfx, track_event, startup |
| 系统级卡顿(通知、多任务) | 系统跟踪(后台模式) | 128 MB (RING_BUFFER) | 300 s | surfaceflinger, input, sched, freq |
| 网络请求导致UI冻屏 | 代码插桩(网络库侧边注入) | 16 MB | 30 s | track_event (net events), sched |
| 线上用户偶发卡顿,无法复现 | 代码插桩 + 远程开关(预埋) | 32 MB | 按用户操作触发 | gfx, view, app自定义事件 |
故障树:选择正确的录制方式
以下决策树可帮助你在接到卡顿报告后,快速定位最合适的Trace采集路径:
排查清单:录制前的检查项
- 确认设备已开启“开发者选项”和“USB调试”。
- 检查存储空间:至少预留500 MB可用空间(避免Trace写入失败)。
- 关闭不必要的后台进程(如游戏、高清视频播放),减少Trace中的噪音。
- 根据卡顿现象选择正确的数据源(必选:sched, gfx, input;可选:freq, idle, am)。
- 录制时长:尽量短(10~30秒),避免产生超大文件。
- 若使用代码插桩,提前确认SDK版本与编译正确。
实践建议:日常开发中,提前在代码内集成Perfetto SDK并添加远程开关(通过Firebase Remote Config或本地调试面板),一旦线上出现卡顿报告,即可远程开启一次Trace,极大缩短数据获取时间。