4. 实时性测量方法论
在 Sitara(AM335x/AM57xx 等)目标板上做实时性优化,第一步不是改内核参数,而是建立一套可复现的测量环境。实时性问题往往表现为偶发的毫秒级抖动,如果测量方法本身不稳定,后续所有调优都失去意义。本节围绕六类工具展开:cyclictest 负责统计调度延迟分布,ftrace 负责内核内部时序追踪,perf 负责采样热点与上下文切换,LTTng 负责全系统低开销事件记录,示波器与 GPIO 打点负责把软件时间轴对齐到硬件物理时间轴。
一、测量对象与指标定义
实时性测量的核心指标是调度延迟(scheduling latency),即从事件就绪(如定时器到期、中断触发)到目标线程真正获得 CPU 执行之间的时间。它由三部分构成:中断关闭时间、中断处理与软中断时间、调度器唤醒与抢占延迟。cyclictest 测的是"定时器到期→线程被唤醒执行"的端到端延迟,而 ftrace 的 irqsoff/preemptoff tracer 可以进一步拆解出中断关闭与抢占关闭的最大区间。
测量前必须固定以下条件,否则数据不可比:CPU 隔离(isolcpus 或 cpuset 把测试线程绑到独占核)、CPU 调频策略固定为 performance、关闭无关后台服务、统一内核版本与配置、记录环境温度。建议在启动参数中加入 isolcpus=1 nohz_full=1 rcu_nocbs=1,并用 taskset -c 1 绑定测试进程。
二、cyclictest:延迟分布统计
cyclictest 是 rt-tests 套件中的核心工具,通过高精度定时器循环测量唤醒延迟。典型命令如下:
cyclictest -m -p 80 -t 1 -a 1 -i 1000 -d 0 -D 300 -h 400 -q
# -m 锁定内存 -p 80 优先级 -t 1 单线程 -a 1 绑定CPU1
# -i 1000 周期1000us -D 300 运行300秒 -h 400 直方图到400us
输出中 Min/Act/Avg/Max 四列最关键,Max 是判断实时性的第一依据。但只看 Max 容易误判:偶发一次 800us 尖峰可能来自一次不可屏蔽中断或 SMI,需要结合直方图看分布形态。若 99.9% 落在 60us 以内、仅个别点超过 200us,说明系统整体可控,问题集中在特定事件;若分布整体右移,则说明基础配置(调频、隔离、内核抢占模型)有问题。建议同时运行 -h 直方图与 -q 静默模式,把结果重定向到文件做多轮对比。
三、ftrace:内核内部时序追踪
当 cyclictest 报出尖峰后,需要定位尖峰发生在内核的哪个阶段。ftrace 通过 function_graph、irqsoff、preemptoff、wakeup_rt 等 tracer 提供函数级时序。常用流程:
cd /sys/kernel/debug/tracing
echo 0 > tracing_on
echo irqsoff > current_tracer
echo 1 > options/function-trace
echo 1 > tracing_on
# 运行负载后
echo 0 > tracing_on
cat trace | head -50
irqsoff tracer 会记录中断被关闭的最长区间及其调用栈,直接指出"谁关中断太久"。wakeup_rt tracer 则记录实时线程从被唤醒到实际运行的延迟,与 cyclictest 的 Max 相互印证。注意 ftrace 本身有开销,长时间开启会改变系统行为,应短时抓取、抓完即关。
四、perf 与 LTTng:采样与全系统事件
perf 适合回答"CPU 时间花在哪里"。用 perf top -e cycles 看热点函数,用 perf sched latency 看各任务的调度延迟统计,用 perf record -e sched:sched_switch -a sleep 10 抓取上下文切换序列。perf 的采样特性决定了它擅长发现统计规律,但不擅长还原单次偶发事件的完整因果链。
LTTng 弥补这一点:它以极低开销记录内核与用户空间事件,通过 babeltrace 或 Trace Compass 还原时间线。典型用法是 lttng create、lttng enable-event -k sched_switch,sched_wakeup,irq_handler_entry、lttng start,运行负载后 stop 并分析。LTTng 的价值在于把中断、软中断、调度、用户态打点放在同一条时间轴上,适合分析"一次抖动前后 1ms 内到底发生了什么"。
五、GPIO 打点与示波器:软硬件时间对齐
纯软件工具无法回答"软件认为的 100us 延迟,在物理世界是否真是 100us"。做法是在关键路径上用 GPIO 翻转打点:在中断入口拉高 GPIO,在线程开始执行时拉低,用示波器测量脉冲宽度,即为物理延迟。Sitara 上可通过 /sys/class/gpio 或直接寄存器操作实现,但用户空间 GPIO 写有几十微秒开销,精确打点应写在内核模块或使用 gpiod_set_value。更严格的做法是用示波器同时抓 PWM 输出与 GPIO 打点,验证定时器精度与调度延迟的叠加效果。
六、建立可复现测量环境的检查清单
| 项目 | 要求 | 验证方式 |
|---|---|---|
| CPU 隔离 | isolcpus/nohz_full/rcu_nocbs 绑定独占核 | cat /proc/cmdline;taskset 确认亲和性 |
| 调频策略 | governor=performance,关闭 C-state | cpupower frequency-info |
| 内核配置 | PREEMPT_RT 或 PREEMPT,开启 ftrace/LTTng | uname -a;/sys/kernel/debug/tracing 存在 |
| 测试负载 | cyclictest 固定参数,多轮取统计 | 保存每轮 Max 与直方图 |
| 硬件打点 | GPIO 脉冲宽度与软件延迟对照 | 示波器截图存档 |
六类工具并非互相替代,而是分层配合:cyclictest 给出延迟分布与 Max 尖峰,ftrace 定位尖峰发生在内核的哪个临界区,perf 与 LTTng 还原事件因果链与热点,GPIO 打点与示波器把软件时间轴锚定到物理时间轴。只有这四层数据相互印证,才能判断一次抖动是配置问题、驱动问题还是硬件问题,也才能让后续的实时性优化有据可依。