背景
在22年进行PREEMPT-RT系统问题的调试时,之前文章在CPU性能优化小记-使用火焰图定位性能问题只是定位解决了其中一个问题,还有一个潜在的问题当时没有续写。然而,最近几乎所有PREEMPT-RT产品上都出现了该问题,影响了非实时任务的CPU吞吐量,引起了大家的广泛关注。因此,有必要对这个问题进行简单记录,希望对大家有所帮助。
本文只说明原因和结论,省略了问题定位流程。
现象
在PREEMPT-RT系统的某些应用场景下,即使没有运行特定的应用程序,整个系统的CPU负载在间隔一段时间后会突然飙升几百毫秒甚至几秒钟。同一型号的不同单板上的持续时间和间隔时间会有所不同。。
无论使用top
还是pidstat
进行观察,只能确定system CPU使用率飙升,且相关线程不定,与具体线程无关。
复现条件
找到一台具有良好实时性的机器,可以是PREEMPT-RT系统或是xenomai+rtnet系统,创建一个高实时任务。该任务使用raw socket周期性地向目标机器发送广播帧,周期可以是500us、1ms或2ms,但发帧周期必须非常准确,在目标机器上查看CPU使用率会看到周期性飙高。
原因
该问题为PREEMPT-RT通病(至少我当前接触到的内核从3.2到5.10均有该问题),整个系统中存在一个以上外部周期事件时就会出现,比如接收PLC发送的周期以太网帧、外部FPGA触发的周期IO中断事件、EtherCAT主站同步到从站参考时钟后中断收发以太网帧等等。
由于外部周期事件(中断)基于的时钟源与PREEMPT-RT系统调度时钟源不同,这两个时钟存在时钟漂移,周期事件会和PREEMPT RT本身的系统调度事件发生周期交越,当两个事件逐渐接近的时候,两个事件都要处理,频繁的上下文导致cpu飙高,系统实时任务的抖动会微微增大。这是PREEMPT-RT系统为了保证外部事件实时性而牺牲CPU吞吐量的机制所导致的。
解决措施
尽管没有彻底解决的方法,但可以尝试以下缓解措施:
- 对于单CPU核系统,系统tick无法关闭,该问题无解;
- 对于SMP多核系统,使能
CONFIG_NO_HZ_FULL
,降低系统周期Tick,同时设置周期事件中断的亲和性到使能CONFIG_NO_HZ_FULL
且没有周期任务运行的CPU上来缓解。
关于Linux时钟子系统,详见本博客之前的文章 linux时间子系统简介。
下一篇文章,我们将探讨由PREEMPT-RT实时机制导致的网络风暴下系统死机问题。