減少由於每個 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 抖動,請執行以下任一操作

  1. 不要使用 eHCA Infiniband 硬體,而是選擇不需要每個 CPU 的 kthreads 的硬體。 這將防止這些 kthreads 首先被建立。 (這對大多數人來說都有效,因為這種硬體雖然重要,但相對較舊,並且產量相對較低。)

  2. 在其他 CPU 上完成所有與 eHCA-Infiniband 相關的工作,包括中斷。

  3. 重新設計 eHCA 驅動程式,使其每個 CPU 的 kthreads 僅在選定的 CPU 上配置。

名稱

irq/%d-%s

目的

處理執行緒化中斷。

要減少其 OS 抖動,請執行以下操作

  1. 使用 irq 親和性強制 irq 執行緒在其他 CPU 上執行。

名稱

kcmtpd_ctr_%d

目的

處理藍牙工作。

要減少其 OS 抖動,請執行以下操作之一

  1. 不要使用藍牙,在這種情況下,這些 kthreads 首先不會被建立。

  2. 使用 irq 親和性強制與藍牙相關的中斷在其他 CPU 上發生,並進一步在其他 CPU 上啟動所有藍牙活動。

名稱

ksoftirqd/%u

目的

線上程化時或在高負載下執行 softirq 處理程式。

要減少其 OS 抖動,每個 softirq 向量必須單獨處理,如下所示

TIMER_SOFTIRQ

執行以下所有操作

  1. 在最大程度上,保持 CPU 在非空閒時遠離核心,例如,透過避免系統呼叫並強制核心執行緒和中斷在其他地方執行。

  2. 使用 CONFIG_HOTPLUG_CPU=y 構建。 引導完成後,強制 CPU 離線,然後使其重新線上。 這會強制重複計時器遷移到其他地方。 如果您擔心多個 CPU,請在使第一個 CPU 重新線上之前強制所有 CPU 離線。 在您使有問題的 CPU 上線後,不要使任何其他 CPU 離線,因為這樣做可能會強制計時器返回到有問題的 CPU 之一。

NET_TX_SOFTIRQ 和 NET_RX_SOFTIRQ

執行以下所有操作

  1. 強制網路中斷到其他 CPU 上。

  2. 在其他 CPU 上啟動任何網路 I/O。

  3. 應用程式啟動後,防止從可能在要消除抖動的 CPU 上執行的任務啟動 CPU 熱插拔操作。 (在啟動應用程式之前,可以強制此 CPU 離線,然後再使其重新線上。)

BLOCK_SOFTIRQ

執行以下所有操作

  1. 強制塊裝置中斷到其他 CPU 上。

  2. 在其他 CPU 上啟動任何塊 I/O。

  3. 應用程式啟動後,防止從可能在要消除抖動的 CPU 上執行的任務啟動 CPU 熱插拔操作。 (在啟動應用程式之前,可以強制此 CPU 離線,然後再使其重新線上。)

IRQ_POLL_SOFTIRQ

執行以下所有操作

  1. 強制塊裝置中斷到其他 CPU 上。

  2. 在其他 CPU 上啟動任何塊 I/O 和塊 I/O 輪詢。

  3. 應用程式啟動後,防止從可能在要消除抖動的 CPU 上執行的任務啟動 CPU 熱插拔操作。 (在啟動應用程式之前,可以強制此 CPU 離線,然後再使其重新線上。)

TASKLET_SOFTIRQ

執行以下一項或多項操作

  1. 避免使用使用 tasklets 的驅動程式。 (此類驅動程式將包含對諸如 tasklet_schedule() 之類的東西的呼叫。)

  2. 將您必須使用的所有驅動程式從 tasklets 轉換為工作佇列。

  3. 強制使用 tasklets 的驅動程式的中斷到其他 CPU 上,並在其他 CPU 上執行涉及這些驅動程式的 I/O。

SCHED_SOFTIRQ

執行以下所有操作

  1. 避免向要消除抖動的 CPU 傳送排程程式 IPI,例如,確保該 CPU 上最多存在一個可執行的 kthread。 如果期望在消除抖動的 CPU 上執行的執行緒喚醒,排程程式將傳送一個 IPI,這可能導致後續的 SCHED_SOFTIRQ。

  2. CONFIG_NO_HZ_FULL=y,並確保使用“nohz_full=”引導引數將要消除抖動的 CPU 標記為自適應時鐘節拍 CPU。 這減少了消除抖動的 CPU 接收的排程程式時鐘中斷的數量,從而最大限度地減少了其被選擇執行在 SCHED_SOFTIRQ 上下文中執行的負載平衡工作的機會。

  3. 在最大程度上,保持 CPU 在非空閒時遠離核心,例如,透過避免系統呼叫並強制核心執行緒和中斷在其他地方執行。 這進一步減少了消除抖動的 CPU 接收的排程程式時鐘中斷的數量。

HRTIMER_SOFTIRQ

執行以下所有操作

  1. 在最大程度上,保持 CPU 在非空閒時遠離核心。 例如,避免系統呼叫並強制核心執行緒和中斷在其他地方執行。

  2. 使用 CONFIG_HOTPLUG_CPU=y 構建。 引導完成後,強制 CPU 離線,然後使其重新線上。 這會強制重複計時器遷移到其他地方。 如果您擔心多個 CPU,請在使第一個 CPU 重新線上之前強制所有 CPU 離線。 在您使有問題的 CPU 上線後,不要使任何其他 CPU 離線,因為這樣做可能會強制計時器返回到有問題的 CPU 之一。

RCU_SOFTIRQ

執行以下至少一項操作

  1. 解除安裝回撥,並透過執行以下所有操作使 CPU 保持在 dyntick-idle 或自適應時鐘節拍狀態

    1. CONFIG_NO_HZ_FULL=y,並確保使用“nohz_full=”引導引數將要消除抖動的 CPU 標記為自適應時鐘節拍 CPU。 將 rcuo kthreads 繫結到可以容忍 OS 抖動的家務處理 CPU。

    2. 在最大程度上,保持 CPU 在非空閒時遠離核心,例如,透過避免系統呼叫並強制核心執行緒和中斷在其他地方執行。

  2. 透過執行以下所有操作,啟用 RCU 以透過 dyntick-idle 遠端執行其處理

    1. 使用 CONFIG_NO_HZ=y 構建。

    2. 確保 CPU 經常進入空閒狀態,允許其他 CPU 檢測到它已經通過了 RCU 靜止狀態。 如果核心使用 CONFIG_NO_HZ_FULL=y 構建,則使用者空間執行也允許其他 CPU 檢測到有問題的 CPU 已經通過了靜止狀態。

    3. 在最大程度上,保持 CPU 在非空閒時遠離核心,例如,透過避免系統呼叫並強制核心執行緒和中斷在其他地方執行。

名稱

kworker/%u:%d%s (cpu, id, 優先順序)

目的

執行工作佇列請求

要減少其 OS 抖動,請執行以下任一操作

  1. 以即時優先順序執行您的工作負載,這將允許搶佔 kworker 守護程序。

  2. 透過將 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 的一部分,即使新增是一個錯誤,也幾乎不可能刪除它。

  3. 執行以下任何避免應用程式無法容忍的抖動所需的操作

    1. 避免使用 oprofile,從而避免來自 wq_sync_buffer() 的 OS 抖動。

    2. 限制您的 CPU 頻率,以便不需要 CPU 頻率調節器,可能需要藉助特殊散熱器或其他冷卻技術。 如果做得正確,並且如果您的 CPU 架構允許,您應該能夠使用 CONFIG_CPU_FREQ=n 構建您的核心,以避免 CPU 頻率調節器定期在每個 CPU 上執行,包括 cs_dbs_timer() 和 od_dbs_timer()。

      警告:請檢查您的 CPU 規格,以確保這在您的特定系統上是安全的。

    3. 截至 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 開銷。

    4. 如果在高階 powerpc 伺服器上執行,請使用 CONFIG_PPC_RTAS_DAEMON=n 構建。 這可以防止 RTAS 守護程式每秒左右在每個 CPU 上執行。 (這將需要編輯 Kconfig 檔案,並會破壞該平臺的 RAS 功能。)這避免了由於 rtas_event_scan() 函式引起的抖動。 警告:請檢查您的 CPU 規格,以確保這在您的特定系統上是安全的。

    5. 如果在 PowerMAC 上執行,請使用 CONFIG_PMAC_RACKMETER=n 構建您的核心以停用 CPU 計量表,從而避免來自 rackmeter_do_timer() 的 OS 抖動。

名稱

rcuc/%u

目的

在 CONFIG_RCU_BOOST=y 核心中執行 RCU 回撥。

要減少其 OS 抖動,請執行以下至少一項操作

  1. 使用 CONFIG_PREEMPT=n 構建核心。 這可以防止首先建立這些 kthreads,並且也消除了對 RCU 優先順序提升的需求。 這種方法對於不需要高度響應性的工作負載是可行的。

  2. 使用 CONFIG_RCU_BOOST=n 構建核心。 這可以防止首先建立這些 kthreads。 只有當您的工作負載從不需要 RCU 優先順序提升時,這種方法才是可行的,例如,如果您確保所有可能在核心中執行的 CPU 都有頻繁的空閒時間。

  3. 使用 CONFIG_RCU_NOCB_CPU=y 構建,並使用 rcu_nocbs= 引導引數從所有易受 OS 抖動影響的 CPU 解除安裝 RCU 回撥。 這種方法可以防止 rcuc/%u kthreads 有任何工作要做,因此它們永遠不會被喚醒。

  4. 確保 CPU 永遠不會進入核心,特別是避免在此 CPU 上啟動任何 CPU 熱插拔操作。 這是防止任何回撥在此 CPU 上排隊的另一種方法,再次防止 rcuc/%u kthreads 有任何工作要做。

名稱

rcuop/%d, rcuos/%d, 和 rcuog/%d

目的

從相應的 CPU 解除安裝 RCU 回撥。

要減少其 OS 抖動,請執行以下至少一項操作

  1. 使用親和性、cgroups 或其他機制強制這些 kthreads 在其他 CPU 上執行。

  2. 使用 CONFIG_RCU_NOCB_CPU=n 構建,這將防止首先建立這些 kthreads。 但是,請注意,這不會消除 OS 抖動,而是將其轉移到 RCU_SOFTIRQ。