幾年前編譯 Linux kernel,ck 補丁集就是系統提速的代名詞。當時編譯核心的三部曲是下 kernel 源碼,打上 ck 補丁集,編譯安裝。後來上游代碼將 ck 補丁集穩定的部分不斷吸收,它的影響力也漸漸消失。
CK 本身對任務調度有很深的造詣,他聰明而經典地實現了 fair scheduling,而實現模式被 Igor 借鑑改進最終寫出了 kernel 用的進程調度管理器 CFS (Completely Fair Scheduler)。不得不順便介紹一下任務調度。Kernel 的進程調度主要是將 CPU 資源分配給各種驅動、進程等等。你可能聽說過,一般人的大腦使用率不足 20% 這種科學或者偽科學言論。但事實是,你電腦上的CPU從來就沒有真正被 100% 的利用過(別跟我說你在資源管理器裡面看到過 CPU 100%,我還見過 101% 呢)。如何將各種運算任務一刻不停又有條不紊的塞給 CPU 處理是一門嚴肅的科學,絕不是電視購物導購能解決的問題。一次塞的運算量少了,CPU 閒著,運算時間增長,電腦慢了;而一次塞的運算多了,CPU 忙不過來,運算又要在門口排隊,電腦也慢了。進程調度主要是用算法解決這個問題,而 Linux Kernel 用的 CFS 據說非常經典,在不同情況下都可達到相當高的 CPU 利用率。而現用 CFS 也是在 2.6.23 才加入的,取代原來 O(1),直接將 Linux 桌面速度從 XX 時代帶入了 XX+N 時代。
兩年前,CK 淡出了核心開發,忽然從江湖中蒸發。幾周前,CK 重出江湖,兩年磨一劍,帶來了 BFS ,全稱 Brain F u c k Scheduler (只認識中間那個單詞的請參考谷歌翻譯),聲稱專為低端硬體設計(我的理解是不超過 10 個 CPU 的電腦電視手機遊戲機都算低端機),說白了就是比 Kernel 默認要更加山崩地裂海枯石爛房價上漲油價飛升的快。BFS 為什麼叫這個名字?為了中文用戶,不能三個詞讓他們一個也不懂吧? 好吧,這名字有點不雅,不過算是直爽。對了,據說 CK 也是看到上面我提到的漫畫才開始劍走偏鋒。真正有幾個人用有上千 CPU 的電腦呢?為什麼要為這種擴展性犧牲桌面性能。BFS 就在其間做了取捨,僅僅支持最多 16 個 CPU ,把問題外沿做小,讓算法更簡單精悍高效。作為原理來講,這足夠解釋速度的來源。對於其它廢問題, CK 專門寫了一個 FAQ。在可以預見的將來,BFS 也不會進入 mainline kernel,說白了是取向問題。
對比
BFS vs CFS,設計上的不同 白天 Con Kolivas 在醫院裡當麻醉師,為人們解除痛苦,業餘的時候借 Linux 解除自己的痛苦。額,Kolivas 學習 Linux 並不是為了解決痛苦,我臆測而已。但據 Kolivas 自述,他接觸 Linux 核心時連 C 語言也沒有學習過。這個事實證明,語言只是一項工具,對問題本質的深入理解才是寫程式的關鍵。可能還有執著,CFS 和 RSDL 之爭導致 Kolivas 離開 Linux 社區,此去經年,當 Kolivas 再次開始看核心代碼的時候,他立即發現 CFS 存在以下幾個設計上的問題:
在 Linux 核心進入 2.6 時,調度器採用 per cpu run queue 從而克服了單一 run queue 的局限。在多 CPU 系統中,單一 run queue 意味著 run queue 成為了系統的瓶頸,因為在同一時刻,一個 CPU 訪問 run queue 時,其他的 CPU 即使空閒也必須等待。當使用 per CPU 的 run queue 之後,每個 CPU 不必再使用大鎖,從而能夠並行地處理調度。
但很多事情都不像第一眼看上去那樣簡單。
Kolivas 發現,採用 per cpu run queue 所帶來的好處會被追求公平性的 load balance 代碼所抵消。在 CFS 調度器中,每顆 CPU 只維護本地 run queue 中所有進程的公平性,為了實現跨 CPU 的調度公平性,CFS 必須定時進行 load balance,將一些進程從繁忙的 CPU 的 run queue 中移到其他空閒的 run queue 中。
這個 load balance 的過程需要獲得其他 run queue 的鎖,這種操作降低了多運行佇列帶來的並行性。
並且在複雜情況下,這種因 load balance 而引入的 footprint 將非常可觀。
當然,load balance 引入的加鎖操作依然比全局鎖的代價要低,這種代價差異隨著 CPU 個數的增加而更加顯著。但請您注意,BFS 並不打算為那些擁有 1024 個 CPU 的系統工作,假若系統中的 CPU 個數有限時,多 run queue 的優勢便不明顯了。