LWN:利用BPF控制CPU調(diào)度器!
關(guān)注了就能看到更多這么棒的文章哦~
Controlling the CPU scheduler with BPF
By Jonathan Corbet
October 21, 2021
DeepL assisted translation
https://lwn.net/Articles/873244/
雖然 BPF 虛擬機在 Linux 出現(xiàn)以來不久之后就存在了,但在大部分時間里,它的作用僅限于(正如其全名 Berkley packet filter 所暗示的那樣)過濾數(shù)據(jù)包。2012 年,隨著 seccomp() 過濾功能的引入,這種情況開始發(fā)生變化,2014 年,隨著 extended BPF 虛擬機的到來,變革的步伐加快了。此時,BPF hook 在許多內(nèi)核子系統(tǒng)中都已經(jīng)存在了。不過,有一個領(lǐng)域仍然沒有 BPF 的身影,那就是 CPU scheduler。如果 Roman Gushchin 的這個 patch set 今后有機會進入 mainline 的話,情況就會得以改變。
內(nèi)核中有幾個 CPU 調(diào)度器,每個都適合一些特定類型的 workload。不過在沒有 realtime 實時進程的系統(tǒng)中,幾乎所有的調(diào)度工作都是由完全公平調(diào)度器(CFS,Completely Fair Scheduler)完成的,以至于大多數(shù)人提到調(diào)度器的時候都是在指它。CFS 是一個非常復(fù)雜的機制。它實現(xiàn)了一套努力學(xué)習(xí)(hard-learned)的啟發(fā)式規(guī)則,希望能使各種 workload 場景下的性能最大化,并有一些控制開關(guān)用在這些啟發(fā)式規(guī)則需要一些調(diào)整的情況下。不過,CPU 調(diào)度是一項復(fù)雜的任務(wù),因此 CFS 的結(jié)果也同樣并不是被所有用戶認(rèn)為總是最佳方案。
Gushchin 在 patch set 的 cover letter 中一開始就提到,他對 CFS 各種控制開關(guān)的效果進行了深入的研究,發(fā)現(xiàn)絕大多數(shù)對 workload 的性能沒有什么影響。最后,總結(jié)了幾個相對簡單的決定:
換句話說,我們的一些 workload 是希望讓那些長期運行的任務(wù)被短暫運行的任務(wù)搶占從而提升性能,而一些只有短暫運行的任務(wù)的 workload 則是希望永遠(yuǎn)不要被搶占,才能提升性能。
在不同的 workload 之中都需要有不同的最佳調(diào)度策略,所以很有必要能根據(jù)需要來調(diào)整策略。Gushchin 指出,大多數(shù) workload 目前使用 CFS 都已經(jīng)挺不錯的了,因此不應(yīng)該僅僅針對其他一些過小眾的 workload 來對 CFS 進行更多調(diào)整。
這正是 BPF 在內(nèi)核其他部分得以存在的典型情況。因為它可以為用戶提供了能夠改變策略的靈活性,既能滿足他們的需要,同時速度又足夠快,因此可以用在像 CPU 調(diào)度器這樣的非常關(guān)注性能的子系統(tǒng)中,而且在不使用它的系統(tǒng)中也不會增加開銷。直到現(xiàn)在還沒有人認(rèn)真嘗試將 BPF 集成到調(diào)度器中,其實這種事情早該出現(xiàn)了。
Gushchin 的 patch set 為影響 CPU 調(diào)度器決策的 BPF program 創(chuàng)建了一個新的 BPF program type(BPF_PROG_TYPE_SCHED)。這些程序有三個掛載點(attachment point):
cfs_check_preempt_tick,在處理調(diào)度器的周期性 timer tick 時被調(diào)用。加載到這里的 BPF 程序可以查看有哪個進程正在運行。如果應(yīng)該允許該進程繼續(xù)運行的話,這個 hook 就可以返回一個負(fù)數(shù)來避免發(fā)生搶占。相反,正數(shù)的返回值則會通知調(diào)度器應(yīng)該把它切換到另一個進程,也就是應(yīng)該發(fā)生搶占。如果返回值為 0 的話,則由調(diào)度器決定該怎么做,就好像這個 hook 從來沒有被運行一樣。
cfs_check_preempt_wakeup,當(dāng)一個進程被內(nèi)核喚醒時會被調(diào)用。負(fù)數(shù)返回值將阻止這個進程搶占當(dāng)前運行的進程,正數(shù)返回值將強制搶占,而 0 則由調(diào)度器自己決定。
cfs_wakeup_preempt_entity,與 cfs_check_preempt_wakeup 類似,但是當(dāng)一個新的進程被選擇執(zhí)行時,它才會被調(diào)用,并且可以影響這里的決定。負(fù)數(shù)返回值表示沒有搶占,正數(shù)返回值則會強制搶占,返回值為 0 則由調(diào)度器的其他決策部分來決定。
Gushchin 指出,在 Facebook 第一次使用這些 hook 的實驗 "看起來很有效果"。他現(xiàn)在來公開 patch set,主要是希望能開始討論如何在調(diào)度器中使用 BPF。
整體來說,這個目標(biāo)似乎并沒有實現(xiàn)。圍繞這些 patch 的對話相對來說比較平淡。最重要的評論來自 Qais Yousef,因為他來自移動場景這個領(lǐng)域,所以對調(diào)度器問題有不同的看法。他指出,在 mobile 場景,廠商傾向于大量修改 CPU 調(diào)度器(見?https://lwn.net/Articles/820825/?介紹的某個廠商的調(diào)度器改動)。Yousef 希望看到調(diào)度器能夠被改進到不再需要這些廠商改動為止,他擔(dān)心如果增加 BPF hook 的話,就會阻礙這一努力:
所以我擔(dān)心的是,這個改動會打開使用 hook 的方式這扇大門,今后也許不再是用來進行平臺特有的微小優(yōu)化。而且,這將阻止人們來正確討論如何真正解決調(diào)度器中的那些真實存在的問題,因為開發(fā)者可以有更簡單的方法了,就是在用戶空間中直接實現(xiàn)他想做的改動。我不確定我們大家是否能控制好這些鉤子的使用。
Yousef 后來承認(rèn),這個功能可能有價值,但建議應(yīng)該嚴(yán)格控制。他說,其他先不說,這里用作調(diào)度器 hook 的 BPF 程序應(yīng)該需要位于在內(nèi)核代碼 tree 之內(nèi),凡是 out-of-tree 的 hook 都要作為 kernel 被 taint 的標(biāo)志,就跟 loadable module 那邊的工作方式一致。
Gushchin 希望能通過讓改動調(diào)度器代碼的工作更加容易,從而使得這個新的 BPF hook 可以用來加速調(diào)度器的開發(fā),而不是拖慢開發(fā)節(jié)奏。同時,他建議要讓供應(yīng)商將他們的調(diào)度器改動采用 BPF program 的方式來實現(xiàn),這可能比他們現(xiàn)在創(chuàng)建的各種 patch 改動方式要更好。
除了這次交流之外,這個 patch set 還沒有收到來自調(diào)度器的核心開發(fā)者或 BPF 社區(qū)的任何重要反饋意見。如果這項工作要被考慮合入 mainline 內(nèi)核的話,這種討論程度肯定是不夠的。允許用戶空間 hook 到調(diào)度器中,這可能確實是比較難以推銷的一個想法,但這個想法似乎不太可能很快消失。不管是好是壞,Linux 內(nèi)核應(yīng)該為各種各樣的用戶服務(wù),要想為每一個用戶都提供最好的解決方案,這總是一個很大的挑戰(zhàn)。
全文完
LWN 文章遵循 CC BY-SA 4.0 許可協(xié)議。
長按下面二維碼關(guān)注,關(guān)注 LWN 深度文章以及開源社區(qū)的各種新近言論~
