文章目录
- 1. 前言
- 2. 今天的德芙,不那么丝滑
- 3. 后记
1. 前言
限于作者能力水平,本文可能存在谬误,因此而给读者带来的损失,作者不做任何承诺。
2. 今天的德芙,不那么丝滑
最近的工作不是很丝滑,本以为三两下会解决的问题,结果还是缠缠绵绵好久;当然,生活有苦也有甜,有时候以为会很难搞的问题,结果没两下又豁然开朗。
甜蜜的经历笔者就不厚道地独享了,这里分享一个不那么丝滑的经历。这两天,遇到这样一个问题,有一个用来音频处理的单线程
程序,运行于一个带 4 核
的 ARM64
平台上,程序启用了实时优先级
。开发阶段,都是通过在命令行手工输入来启动,调试的差不多了,就准备使用开机自启动的方式,做进一步地测试,于是在 /etc/init.d
目录下加入启动脚本,然后重启系统,结果就傻眼了,系统启动十次,就有九次播放音频卡顿,这完全出乎笔者意料之外。踅摸踅摸,看看哪里出了差错,一时没有头绪。折腾几次,突然一条内核日志引起了笔者的注意:
sched: RT throttling activated
这个似乎让笔者看到一些光亮,既然有线索,那就不能轻易放过。一番调查,发现确实是笔者的音频测试程序触发的该条内核日志。但是为什么?只有在开机自启动方式才会触发该条内核日志、才会出问题?一时间不得要领。查看屡次启动的内核日志,结合到并非每次都会出现问题
,朦朦胧胧的似乎抓到了什么,但又看不真切。笔者知道,胡乱推测,除了浪费时间不会得到什么。还是得从唯二线索入手。目前手头有两条线索:
1. 内核日志sched: RT throttling activated2. 并非每次都会出问题
对于第 2
条线索,暂时不知道能得出什么结论,暂时先放一边;对于第 1
条线索的内核日志,结合笔者了解对 Linux 实时进程带宽 的理解,笔者推断,可能是因为在开机自启动的场景下,系统运行进程很少,因此音频实时进程没有什么竞争,很快达到了系统默认实施进程 CPU 资源上限的 95%
,触发了实时进程限制的内核日志。顺着这个思路往下想,那是不是可以推迟音频测试程序的启动时间,越是往后越好,等到启动足够多的进程后,再启动音频测试程序,就不会引发系统对实时进程的限制,从而解决问题?再结合第 2
条线索,在偶尔的不出现问题的那些次数,发现音频进程的 PID
,对比其它开机自启动程序,都是 PID
较大的几个之一,这基本可以表明音频测试程序的启动时间,在开机自启动程序里面是靠后的,这样,第 2
条线索也能够对起来了。
既然有了合理地推测(至少看起是这样),又对上了已有的线索。那有了足够的理由去进行验证了,笔者想办法延迟了音频测试程序的启动时间:
1. 按 /etc/init.d 下脚本的启动排序方式,更改了音频程序启动脚本名称,让它更靠后启动。
2. 插入一个无用的 busy loop 无用程序的启动脚本,让这个脚本在音频程序启动脚本之前执行。这个 busyloop 得花点心思,它有和 CPU 核心数相同的线程数,每个线程绑定一个核心。这么做的目的是保证每个 CPU 核心上都有一定的工作量,这样不管单线程的音频测试程序在哪个 CPU 核心上运行,都不会达到 Linux 对该 CPU 核心上实时进程占有资源上限。
3. 音频程序启动脚本启动音频测试程序前,插入几秒钟的延迟。
经测试验证,光是采用 1.
,几乎没有太大效果,大多数时候都还是会有问题;如果同时结果策略 2.
,有较大改善,但还是有较高概率出问题;再结合策略 3.
,则很少会出问题,但还是无法完全避免。这时候只得从代码
本身入手,使用策略
4. 在适当的地方插入适量的睡眠时间
同时移除策略 1.,2.,3.
,经过一段时间测试,目前没有再重现问题。
3. 后记
音频程序开机自启动方式引发的问题,最终通过在代码插入适量的睡眠时间,解决了问题(至少目前看来如此);但手工从命令行启动的方式,即使不加入睡眠时间,也没有引发 RT throttling
,这是个值得进一步深思的问题,一个可能合理的推测是:系统负载上来后,即使实时进程,也没法达到 CPU 对实施进程资源的上限了
。当然,这需要更衣进一步的证据,等笔者有了结论,再来与大家一起分享,我们今天的故事,到这里就结束了。