减少由于每个 CPU 的 kthreads 导致的 OS 抖动¶
本文档列出了 Linux 内核中的每个 CPU 的 kthreads,并提供了控制其 OS 抖动的选项。 请注意,此处未列出非每个 CPU 的 kthreads。 要减少来自非每个 CPU 的 kthreads 的 OS 抖动,请将它们绑定到专用于此类工作的“家务处理” CPU。
参考¶
SMP IRQ 亲和性: 将中断绑定到 CPU 集合。
Documentation/admin-guide/cgroup-v1: 使用 cgroups 将任务绑定到 CPU 集合。
man taskset:使用 taskset 命令将任务绑定到 CPU 集合。
man sched_setaffinity:使用 sched_setaffinity() 系统调用将任务绑定到 CPU 集合。
/sys/devices/system/cpu/cpuN/online:控制 CPU N 的热插拔状态,写入“0”以离线,写入“1”以在线。
为了定位 CPU N 上内核生成的 OS 抖动
cd /sys/kernel/tracing echo 1 > max_graph_depth # 增加“1”以获得更多细节 echo function_graph > current_tracer # 运行工作负载 cat per_cpu/cpuN/trace
kthreads¶
- 名称
ehca_comp/%u
- 目的
定期处理与 Infiniband 相关的工作。
要减少其 OS 抖动,请执行以下任一操作
不要使用 eHCA Infiniband 硬件,而是选择不需要每个 CPU 的 kthreads 的硬件。 这将防止这些 kthreads 首先被创建。 (这对大多数人来说都有效,因为这种硬件虽然重要,但相对较旧,并且产量相对较低。)
在其他 CPU 上完成所有与 eHCA-Infiniband 相关的工作,包括中断。
重新设计 eHCA 驱动程序,使其每个 CPU 的 kthreads 仅在选定的 CPU 上配置。
- 名称
irq/%d-%s
- 目的
处理线程化中断。
要减少其 OS 抖动,请执行以下操作
使用 irq 亲和性强制 irq 线程在其他 CPU 上执行。
- 名称
kcmtpd_ctr_%d
- 目的
处理蓝牙工作。
要减少其 OS 抖动,请执行以下操作之一
不要使用蓝牙,在这种情况下,这些 kthreads 首先不会被创建。
使用 irq 亲和性强制与蓝牙相关的中断在其他 CPU 上发生,并进一步在其他 CPU 上启动所有蓝牙活动。
- 名称
ksoftirqd/%u
- 目的
在线程化时或在高负载下执行 softirq 处理程序。
要减少其 OS 抖动,每个 softirq 向量必须单独处理,如下所示
TIMER_SOFTIRQ¶
执行以下所有操作
在最大程度上,保持 CPU 在非空闲时远离内核,例如,通过避免系统调用并强制内核线程和中断在其他地方执行。
使用 CONFIG_HOTPLUG_CPU=y 构建。 引导完成后,强制 CPU 离线,然后使其重新在线。 这会强制重复计时器迁移到其他地方。 如果您担心多个 CPU,请在使第一个 CPU 重新在线之前强制所有 CPU 离线。 在您使有问题的 CPU 上线后,不要使任何其他 CPU 离线,因为这样做可能会强制计时器返回到有问题的 CPU 之一。
NET_TX_SOFTIRQ 和 NET_RX_SOFTIRQ¶
执行以下所有操作
强制网络中断到其他 CPU 上。
在其他 CPU 上启动任何网络 I/O。
应用程序启动后,防止从可能在要消除抖动的 CPU 上运行的任务启动 CPU 热插拔操作。 (在启动应用程序之前,可以强制此 CPU 离线,然后再使其重新在线。)
BLOCK_SOFTIRQ¶
执行以下所有操作
强制块设备中断到其他 CPU 上。
在其他 CPU 上启动任何块 I/O。
应用程序启动后,防止从可能在要消除抖动的 CPU 上运行的任务启动 CPU 热插拔操作。 (在启动应用程序之前,可以强制此 CPU 离线,然后再使其重新在线。)
IRQ_POLL_SOFTIRQ¶
执行以下所有操作
强制块设备中断到其他 CPU 上。
在其他 CPU 上启动任何块 I/O 和块 I/O 轮询。
应用程序启动后,防止从可能在要消除抖动的 CPU 上运行的任务启动 CPU 热插拔操作。 (在启动应用程序之前,可以强制此 CPU 离线,然后再使其重新在线。)
TASKLET_SOFTIRQ¶
执行以下一项或多项操作
避免使用使用 tasklets 的驱动程序。 (此类驱动程序将包含对诸如 tasklet_schedule() 之类的东西的调用。)
将您必须使用的所有驱动程序从 tasklets 转换为工作队列。
强制使用 tasklets 的驱动程序的中断到其他 CPU 上,并在其他 CPU 上执行涉及这些驱动程序的 I/O。
SCHED_SOFTIRQ¶
执行以下所有操作
避免向要消除抖动的 CPU 发送调度程序 IPI,例如,确保该 CPU 上最多存在一个可运行的 kthread。 如果期望在消除抖动的 CPU 上运行的线程唤醒,调度程序将发送一个 IPI,这可能导致后续的 SCHED_SOFTIRQ。
CONFIG_NO_HZ_FULL=y,并确保使用“nohz_full=”引导参数将要消除抖动的 CPU 标记为自适应时钟节拍 CPU。 这减少了消除抖动的 CPU 接收的调度程序时钟中断的数量,从而最大限度地减少了其被选择执行在 SCHED_SOFTIRQ 上下文中运行的负载平衡工作的机会。
在最大程度上,保持 CPU 在非空闲时远离内核,例如,通过避免系统调用并强制内核线程和中断在其他地方执行。 这进一步减少了消除抖动的 CPU 接收的调度程序时钟中断的数量。
HRTIMER_SOFTIRQ¶
执行以下所有操作
在最大程度上,保持 CPU 在非空闲时远离内核。 例如,避免系统调用并强制内核线程和中断在其他地方执行。
使用 CONFIG_HOTPLUG_CPU=y 构建。 引导完成后,强制 CPU 离线,然后使其重新在线。 这会强制重复计时器迁移到其他地方。 如果您担心多个 CPU,请在使第一个 CPU 重新在线之前强制所有 CPU 离线。 在您使有问题的 CPU 上线后,不要使任何其他 CPU 离线,因为这样做可能会强制计时器返回到有问题的 CPU 之一。
RCU_SOFTIRQ¶
执行以下至少一项操作
卸载回调,并通过执行以下所有操作使 CPU 保持在 dyntick-idle 或自适应时钟节拍状态
CONFIG_NO_HZ_FULL=y,并确保使用“nohz_full=”引导参数将要消除抖动的 CPU 标记为自适应时钟节拍 CPU。 将 rcuo kthreads 绑定到可以容忍 OS 抖动的家务处理 CPU。
在最大程度上,保持 CPU 在非空闲时远离内核,例如,通过避免系统调用并强制内核线程和中断在其他地方执行。
通过执行以下所有操作,启用 RCU 以通过 dyntick-idle 远程执行其处理
使用 CONFIG_NO_HZ=y 构建。
确保 CPU 经常进入空闲状态,允许其他 CPU 检测到它已经通过了 RCU 静止状态。 如果内核使用 CONFIG_NO_HZ_FULL=y 构建,则用户空间执行也允许其他 CPU 检测到有问题的 CPU 已经通过了静止状态。
在最大程度上,保持 CPU 在非空闲时远离内核,例如,通过避免系统调用并强制内核线程和中断在其他地方执行。
- 名称
kworker/%u:%d%s (cpu, id, 优先级)
- 目的
执行工作队列请求
要减少其 OS 抖动,请执行以下任一操作
以实时优先级运行您的工作负载,这将允许抢占 kworker 守护进程。
通过将 WQ_SYSFS 传递给该工作队列的
alloc_workqueue()
,可以在 sysfs 文件系统中使给定的工作队列可见。 可以使用/sys/devices/virtual/workqueue/*/cpumask
sysfs 文件将这样的工作队列限制到给定的 CPU 子集。 可以使用“ls /sys/devices/virtual/workqueue”显示 WQ_SYSFS 工作队列的集合。 也就是说,工作队列维护者希望告诫人们不要不加选择地将 WQ_SYSFS 洒在所有工作队列上。 需要谨慎的原因是添加 WQ_SYSFS 很容易,但由于 sysfs 是正式用户/内核 API 的一部分,即使添加是一个错误,也几乎不可能删除它。执行以下任何避免应用程序无法容忍的抖动所需的操作
避免使用 oprofile,从而避免来自 wq_sync_buffer() 的 OS 抖动。
限制您的 CPU 频率,以便不需要 CPU 频率调节器,可能需要借助特殊散热器或其他冷却技术。 如果做得正确,并且如果您的 CPU 架构允许,您应该能够使用 CONFIG_CPU_FREQ=n 构建您的内核,以避免 CPU 频率调节器定期在每个 CPU 上运行,包括 cs_dbs_timer() 和 od_dbs_timer()。
警告:请检查您的 CPU 规格,以确保这在您的特定系统上是安全的。
截至 v3.18,Christoph Lameter 的按需 vmstat worker 提交可防止由于 CONFIG_SMP=y 系统上的 vmstat_update() 导致的 OS 抖动。 在 v3.18 之前,不可能完全消除 OS 抖动,但您可以通过向 /proc/sys/vm/stat_interval 写入一个大值来降低其频率。 默认值为 HZ,间隔为一秒。 当然,更大的值会使您的虚拟内存统计信息更新得更慢。 当然,您也可以以实时优先级运行您的工作负载,从而抢占 vmstat_update(),但如果您的工作负载是 CPU 密集型的,这是一个坏主意。 但是,Christoph Lameter 有一个 RFC 补丁(基于 Gilad Ben-Yossef 之前的补丁),它减少甚至消除了 https://lore.kernel.org/r/00000140e9dfd6bd-40db3d4f-c1be-434f-8132-7820f81bb586-000000@email.amazonses.com 上一些工作负载的 vmstat 开销。
如果在高端 powerpc 服务器上运行,请使用 CONFIG_PPC_RTAS_DAEMON=n 构建。 这可以防止 RTAS 守护程序每秒左右在每个 CPU 上运行。 (这将需要编辑 Kconfig 文件,并会破坏该平台的 RAS 功能。)这避免了由于 rtas_event_scan() 函数引起的抖动。 警告:请检查您的 CPU 规格,以确保这在您的特定系统上是安全的。
如果在 PowerMAC 上运行,请使用 CONFIG_PMAC_RACKMETER=n 构建您的内核以禁用 CPU 计量表,从而避免来自 rackmeter_do_timer() 的 OS 抖动。
- 名称
rcuc/%u
- 目的
在 CONFIG_RCU_BOOST=y 内核中执行 RCU 回调。
要减少其 OS 抖动,请执行以下至少一项操作
使用 CONFIG_PREEMPT=n 构建内核。 这可以防止首先创建这些 kthreads,并且也消除了对 RCU 优先级提升的需求。 这种方法对于不需要高度响应性的工作负载是可行的。
使用 CONFIG_RCU_BOOST=n 构建内核。 这可以防止首先创建这些 kthreads。 只有当您的工作负载从不需要 RCU 优先级提升时,这种方法才是可行的,例如,如果您确保所有可能在内核中执行的 CPU 都有频繁的空闲时间。
使用 CONFIG_RCU_NOCB_CPU=y 构建,并使用 rcu_nocbs= 引导参数从所有易受 OS 抖动影响的 CPU 卸载 RCU 回调。 这种方法可以防止 rcuc/%u kthreads 有任何工作要做,因此它们永远不会被唤醒。
确保 CPU 永远不会进入内核,特别是避免在此 CPU 上启动任何 CPU 热插拔操作。 这是防止任何回调在此 CPU 上排队的另一种方法,再次防止 rcuc/%u kthreads 有任何工作要做。
- 名称
rcuop/%d, rcuos/%d, 和 rcuog/%d
- 目的
从相应的 CPU 卸载 RCU 回调。
要减少其 OS 抖动,请执行以下至少一项操作
使用亲和性、cgroups 或其他机制强制这些 kthreads 在其他 CPU 上执行。
使用 CONFIG_RCU_NOCB_CPU=n 构建,这将防止首先创建这些 kthreads。 但是,请注意,这不会消除 OS 抖动,而是将其转移到 RCU_SOFTIRQ。