我正在尝试禁用本地计时器中断以降低延迟。我在内核配置中启用了完全无滴答模式,并且为相关核心设置了启动参数 nohz_full。
然而,当我通过 /proc/interrupts 查看中断计数时,我看到本地计时器中断每个核心每秒计数 1000 次,这意味着完全无滴答不起作用。
无滴答模式文档指出,要无滴答地工作,该核心上只需要一个正在运行的进程。
当我查看顶部时,我在给定核心(本例中为核心 1)下看到以下内容:
19 root RT 0 0 0 0 S 0.0 0.0 0:00.00 1 watchdog/1
20 root -2 0 0 0 0 S 0.0 0.0 0:02.15 1 rcuc/1
21 root RT 0 0 0 0 S 0.0 0.0 0:00.04 1 migration/1
22 root -2 0 0 0 0 S 0.0 0.0 0:00.25 1 ksoftirqd/1
23 root RT 0 0 0 0 S 0.0 0.0 0:00.00 1 posixcputmr/1
24 root 20 0 0 0 0 S 0.0 0.0 0:00.00 1 kworker/1:0
25 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 1 kworker/1:0H
我确实知道其中一些是内核线程。这就是我的完全无滴答模式不起作用的原因吗?
答案1
用eg激活的完全无滴答模式nohz_full=cpux-cpuy
确实只有在只有一个时才有效可运行每个nohz_full
CPU上的任务:
除非给定 CPU 只有一个可运行任务,否则自适应时钟不会执行任何操作,即使在许多其他情况下不需要调度时钟时钟。
(参见文档/定时器/NO_HZ.txt)
因此,如果您nohz_full
使用 ps 检查 CPU,则显式查找可运行任务是有意义的 - 例如:
$ ps -e -L -o cpuid,pid,lwp,state,pri,rtprio,class,wchan:20,comm \
| awk '$1 == '$mycpunr
(即查看状态栏)
这意味着 CPU 上可以有一些额外的任务,nohz_full
只要它们不可运行。
只要使用nohz_full=
,就不会阻止内核在选定的 CPU 上调度用户/内核线程。因此,通常还会隔离这些 CPU 以避免其他线程的干扰。例如:
nohz_full=cpux-cpuy isolcpus=cpux-cpuy
(参见Linux 内核参数)
通过这些选项,独立 CPU 上的线程nohz_full
仍然可以被中断,例如通过计时器和 RCU 操作。
因此,如果您想最大限度地减少隔离线程的延迟,您需要禁用其他中断源。
您可以检查/proc/timer_list
隔离 CPU 上仍处于活动状态的定时器。
隔离 CPU 上可能显示的定时器的常见示例是watchdog_timer_fn
与机器检查异常 (MCE) 功能相关的定时器。
您可以通过进一步禁用这些中断内核选项,例如:
nowatchdog mce=ignore_ce
查看/proc/interrupts
计数器是检查硬件引起的中断的好方法。中断的另一个来源是软中断,因此还必须检查/proc/softirqs
计数器。
例如,为了最大限度地减少隔离 CPU 上与 RCU 相关的中断,可以将 RCU 回调卸载到内核线程,将它们迁移到非隔离 CPU,并通过添加内核选项使隔离 CPU 免于通知回调线程:
rcu_nocb_poll
该选项必须rcu_nocbs=
有效,但nohz_full=
已经暗示了rcu_nocbs=
指定的 CPU。
请注意,您必须明确将卸载的 RCU 回调线程移至内务处理 CPU - 通过显式设置这些线程的 CPU 关联性。以金枪鱼为例(到 CPU 0):
# tuna -U -t 'rcu*' -c 0 -m
内核文档文档/kernel-per-CPU-kthreads.txt描述了更多的中断源(又名操作系统抖动),并展示了如何通过启用跟踪运行测试负载来定位它们。