cyclictest 的真实延迟抖动应关注直方图尾部累积值(如99.9%分位和>50μs占比),而非max;需关闭cpu调频、隔离cpu、禁用timer_migration、使用rt内核并验证调度策略,同时排查c-state、内存分配等用户态瓶颈。

怎么用 cyclictest 测出真实延迟抖动
直接跑 cyclictest -l 10000 -i 1000 -h 500 得到的 Max 值,大概率不是你系统的真实最差延迟——它受测量工具自身调度干扰、时钟源精度、CPU 频率跳变影响太大。
关键在于让测试尽可能“贴近硬件”:关闭 CPU 频率调节(cpupower frequency-set -g performance),绑定到隔离 CPU(isolcpus=2,3 内核启动参数),并用 taskset -c 2 运行 cyclictest。否则测出来的是“Linux 普通进程调度抖动”,不是实时线程能压到多低。
-
-i 1000表示每 1ms 触发一次定时器,但若系统HZ是 250 或使用NO_HZ_FULL,实际精度可能被限制;建议搭配/proc/sys/kernel/timer_migration=0 -
-h设置直方图上限,别设太小(如-h 100),否则超限值全堆在最后一格,看不出分布尾部 - 加
-q(quiet)减少输出开销,避免 printf 本身引入抖动
cyclictest 输出里哪个值真该盯住
别只看 Max。它只是 10000 次中的最大单次延迟,偶然性太强;真正反映系统稳定性的,是 Latency histogram 尾部累积值,尤其是 99.9% 分位(99.9%: ... us)和直方图中 >50μs 的计数占比。
PREEMPT_RT 补丁的作用,不是把 Max 从 200μs 压到 10μs,而是把 >50μs 的样本从几百次降到个位数——这意味着中断响应、锁竞争、内核抢占点这些“偶发长尾”被大幅收敛。
- 原始内核下,
cyclictest常见错误现象:Max突然跳到 500–2000μs,伴随dmesg里rcu_preempt detected stalls或watchdog: BUG: soft lockup - PREEMPT_RT 启用后,
Max可能仍偶尔冲高(比如触发 page fault 或 slab 重分配),但 99.9% 分位应稳定在 15–30μs 区间(X86-64 + Intel i7) - 注意
cyclictest默认用SCHED_FIFO,若没配RLIMIT_RTPRIO,会静默降级为SCHED_OTHER,输出里显示policy=OTHER—— 这时所有数据都无效
为什么开了 PREEMPT_RT,cyclictest 还是飘高
PREEMPT_RT 不是万能开关。它解决的是内核态可抢占性,但用户空间的延迟瓶颈常来自别处:内存分配、文件 I/O、NUMA 跨节点访问、甚至 BIOS 中的 C-state 设置。
最容易被忽略的是 intel_idle.max_cstate=1 启动参数。现代 CPU 进入 C6/C7 状态要几十微秒唤醒,而 cyclictest 的 1ms 定时器刚好频繁触发唤醒-睡眠循环,导致周期性大延迟尖峰。
- 检查是否真用了 RT 内核:
uname -r应含rt(如5.10.104-rt69),且cat /sys/kernel/debug/sched_features | grep PREEMPT显示PREEMPT开启 -
vmstat 1看cs(context switch)是否异常高,可能是其他进程持续抢占 CPU - 用
perf record -e 'sched:sched_switch' -C 2 -g抓一段时间,看高延迟时刻是否切到了ksoftirqd或kworker上
cyclictest 和真实应用延迟的差距在哪
cyclictest 测的是“空载定时器精度”,而你的实时音视频或运动控制应用,往往带着 memcpy、浮点计算、DMA 同步、PCIe 设备轮询——这些操作会触发 cache miss、TLB miss、锁竞争,cyclictest 完全不覆盖。
它只能告诉你“底层调度有没有硬伤”。如果 cyclictest 99.9%
- 验证驱动是否适配 RT:检查设备驱动是否用
spin_lock_irqsave替代了spin_lock,是否避免在中断上下文中调用mutex_lock -
cyclictest -a -t1 -n -i 1000(-n表示 no-fork,单线程)更接近轻量应用行为;加-t2后若延迟翻倍,说明 SMP 锁争用严重 - 别信“RT 补丁让 Linux 变成 VxWorks”——它只是把内核里几十个不可抢占点改成可抢占,其余机制(页表管理、内存回收、热插拔)依然存在软实时边界
真正难调的,永远是那个没打印日志、不抛异常、只在特定负载组合下才冒头的 100μs 毛刺。这时候 cyclictest 只是个起点,不是答案。









