第4章:性能测量工具准备——perfetto抓取systrace、sched_wakeup/sched_switch事件、/proc//stat读取
在RTL(Real-Time Linux)环境下,SystemUI的线程调度行为与通用Linux存在显著差异。本章聚焦性能测量工具的准备工作,涵盖perfetto的systrace抓取、sched_wakeup/sched_switch事件的捕获与解析,以及通过/proc/
4.1 perfetto核心事件类型与配置
perfetto是Android系统首选的性能追踪工具。针对RTL下的线程调度分析,需启用以下关键数据源:
- ftrace events: 捕获内核调度器事件(sched_switch, sched_wakeup, sched_wakeup_new)。
- process stats: 记录进程的cpu、mem、io等资源使用统计。
- atrace categories: 收集应用层(SystemUI)的同步、Vsync、Input等标记。
调度事件原理
sched_switch记录线程的“离开CPU”与“进入CPU”时刻,直接反映线程被抢占、休眠或唤醒的时间点。sched_wakeup记录唤醒者与被唤醒者的pid,是追踪线程响应延迟的直接证据。
sched_switch记录线程的“离开CPU”与“进入CPU”时刻,直接反映线程被抢占、休眠或唤醒的时间点。sched_wakeup记录唤醒者与被唤醒者的pid,是追踪线程响应延迟的直接证据。
以下为perfetto抓取的典型配置片段(trace config protobuf格式):
# 关键配置:启用内核调度事件
data_sources {
config {
name: "linux.ftrace"
ftrace_config {
ftrace_events: "sched/sched_switch"
ftrace_events: "sched/sched_wakeup"
ftrace_events: "sched/sched_wakeup_new"
buffer_size_kb: 4096
}
}
}
# 启用进程统计
data_sources {
config {
name: "linux.process_stats"
process_stats_config {
scan_all_processes: true
proc_stats_interval_ms: 100
}
}
}
4.2 通过adb命令触发trace抓取
生产环境或测试设备上,使用perfetto命令抓取指定时长与大小的trace:
# 将配置文件推送到设备
adb push trace_config.pbtx /data/local/tmp/trace_config.pbtx
# 使用perfetto命令开始抓取(指定输出文件与缓冲区大小)
adb shell perfetto \
-c /data/local/tmp/trace_config.pbtx \
-o /data/local/tmp/systemui_trace.perfetto-trace \
--txt \
--duration 15s \
--buffer-size 64mb
# 拉取trace到本地
adb pull /data/local/tmp/systemui_trace.perfetto-trace .
RTL环境适配:
若设备未预装perfetto,可通过
若设备未预装perfetto,可通过
adb push手动推送perfetto二进制(取自对应平台)。同时,确保内核配置项CONFIG_FTRACE、CONFIG_SCHED_TRACING已启用。
4.3 /proc/<pid>/stat的字段提取与优先级解析
/proc/
| 字段索引 | 含义 | RTL调优关注点 |
|---|---|---|
| 2 | 进程状态(S/R/D/T/t) | 频繁“D”状态可能表示I/O阻塞 |
| 17 | nice值 | RTL下nice>0可能被抢占 |
| 18 | 调度策略(0=normal, 1=FIFO, 2=RR) | 确认是否使用SCHED_FIFO |
| 39 | CPU时间片(sum_exec_runtime) | 线程累积执行时间 |
| 40 | 线程优先级(prio) | 动态优先级,实时任务通常0-99 |
读取方法(shell脚本示例):
# 获取SystemUI主线程PID
SYSUI_PID=$(adb shell pidof com.android.systemui | awk '{print $NF}')
# 循环读取stat(每秒10次,低开销)
while true; do
adb shell "cat /proc/$SYSUI_PID/stat" | \
awk '{print "pid:", $1, "state:", $3, "prio:", $18, "policy:", $41}'
sleep 0.1
done
常见错误:
在RTL上直接
在RTL上直接
cat /proc/<pid>/stat可能返回空值或<unknown>,原因通常是进程快速退出或stat文件权限不足。解决方案:使用sched_setattr或sysfs查询实时优先级更稳定。
4.4 三工具集成分析流程
将perfetto的sched事件与/proc/stat的轮询数据结合,可构建完整的线程响应延迟链路。下图展示了数据流与核心分析步骤:
4.5 调试与稳定性检查
- 验证事件完整性:在perfetto trace中搜索
sched_switch条目,若无数据则检查ftrace权限(需root或adb shell setenforce 0)。 - 时间对齐:perfetto的时间戳基于CLOCK_MONOTONIC,/proc/stat轮询需自行记录高精度时间戳(如使用
clock_gettime),否则无法精确对齐。 - 性能开销:不要在生产环境高频(<1ms)轮询/proc/stat,建议间隔≥50ms。perfetto的缓冲区大小设为64MB可避免高频丢失早期数据。
部署检查清单:
1. 确认设备有无perfetto二进制(
2. 确认ftrace目录挂载(
3. 对SystemUI的PID做cap_sys_nice权限检查,否则无法读取实时优先级字段。
4. 预跑一次短trace(5s),快速验证sched_wakeup/sched_switch事件存在。
1. 确认设备有无perfetto二进制(
adb shell which perfetto)。2. 确认ftrace目录挂载(
adb shell ls /sys/kernel/debug/tracing/)。3. 对SystemUI的PID做cap_sys_nice权限检查,否则无法读取实时优先级字段。
4. 预跑一次短trace(5s),快速验证sched_wakeup/sched_switch事件存在。
4.6 常见错误与解决
| 现象 | 原因 | 解决 |
|---|---|---|
| trace中无sched事件 | ftrace未开启或权限不足 | adb shell setenforce 0;确认内核配置 |
| /proc/stat返回<unknown> | stat字段格式变更(RTL定制内核) | 使用procps-ng或直接解析字段索引 |
| perfetto命令找不到 | 设备未集成perfetto用户空间工具 | 从Android平台单独推送perfetto可执行文件 |
| trace文件过大导致拉取失败 | 缓冲区设置过大或持续时间过长 | --buffer-size 32mb --duration 10s |
通过上述工具的准备与正确配置,可获得观察RTL下SystemUI线程调度行为所需的原始数据,为后续的优先级分析和调优打下基础。