google怎樣使用linux(內核)

google怎樣使用linux(內核)



今年的linux內核開發大會上,google的開發人員也上臺做了名爲“how google use linux"的演講。我斗膽翻譯註解一番——括號內爲註解,歡迎讀者斧正。

(前面幾段講google對linux kernel代碼的管理及跟進,偏細碎,不翻譯了)
在google爲linux加入的代碼中,3/4是對內核核心的改動,設備驅動代碼只是其中相對較小的一部分。
(linux發展到現在這個階段,需要加入的新的設備驅動已經越來越少了)

如果google要與linux社區的合作開發,那將面臨一系列問題。跟上linux代碼的主幹太難——它的代碼更新的太快了。在一個大型項目 裏,開發者對補丁的提交、重改確實是個問題。Alan Cox對此的回答十分簡單:人總是貪得無厭的,但有時候就應該簡單的對他們說”不“。
(Alan Cox是linux kernel的二號功臣,現已加入Intel公司。我覺得Intel這樣的CPU公司很適合內核開發者)

在CPU調度上,google發現想改用新的cfs(“完全公平調度”,由Con Kolivasy在2.6.23中加入內核)非常麻煩。由於太麻煩,google不得不倒回去把O(1) sheduler(2.6.23前內核使用的調度算法,想知道這段具體的歷史,可以參考另一篇cfs文章)移植到2.6.26上,一切才能運轉起來。內核對sched_yield()語義的更改也造成了麻 煩,尤其當google使用用戶態鎖時。高優先級的線程會對服務器的負載均衡(這裏的負載均衡指的是一臺服務器上多個CPU對多任務的分配處理,不是指分佈式)造成影響,哪怕這些線程只是運行很短的時間。而負載均衡很重要:google通常在16-32核的服務器上跑5000個線程(好詭譎的用法!)。

在內存管理上,新的linux內核改變了對髒數據的管理,導致出現了大量主動的寫回操作(髒數據要寫回硬盤)。系統很容易出現這種局 面:kswaped(swap進程)會產生大量小的I/O操作,塞滿塊設備的請求隊列,結果造成別的寫回無法完成(寫回“飢餓”);這個問題已經通過 “per-DBI寫回機制”補丁在2.6.32內核中解決了。
(per-DBI的主要原理是塊設備不再只有一個等待隊列,而是多個,每個“硬盤軸”一個隊列,因爲硬盤軸是一個硬件上的真正的工作單位。這樣,對裝配多個硬盤的服務器會有很好的I/O性能。不過我個人猜測,如果能把kswaped的小請求合併,是否也能提高性能呢?)

如上所述,google在系統中啓動很多線程——不尋常的用法。他們發現如果向一個大的線程組發信號,會造成運行隊列鎖的大量競爭。google 還發現mmap_sem信號量(是內核結構 struct mm_struct中用來保護mmap空間的內核信號量)有競爭問題;一個睡眠的讀者會阻塞寫者,而這個寫者又阻塞了其他讀者,最後造成系統死鎖。內核應該修改,拿到信號量以後不要 再等待I/O。
(google所說的信號對線程組造成的問題估計是“驚羣效應”,就是很多任務睡在一個隊列上,一個喚醒操作會造成他們都突然醒來,結果必然是資源擁擠。我個人認爲這不是linux的問題,這是google使用linux的方法太奇特了,所以內核開發者沒有注意到)

google大量使用了OOM killer來減輕高負載服務器的負擔。這樣做有一定的麻煩,當擁有鎖的進程被OOM殺掉時(鎖並不會釋放,結果就阻塞了別的任務)。Mike(演講人) 很想知道爲什麼kernel費那麼大勁搞出OOM killer來,而不是簡單的在分配內存失敗後返回一個錯誤。
(不光Mike,大家都有這樣的 疑問,估計答案只能在內核郵件組裏找了。而google所說的那個“進程被殺鎖卻沒釋放、造成阻塞”的問題,yahoo在freebsd-4.11的時代 就已經解決了,用了很巧很輕量級的辦法。大家都覺得google的技術最牛,其實公正的說,牛公司牛人很多,只是大家沒他那麼高調而已。但對國內來說,能 通過改進內核來提高服務器的公司,也真是鳳毛麟角了。)

(此外略去一段google對內核開發工作的分類,看不太懂)

google增加了一種SCHED_GIDLE的調度類,是真正的空閒類;如果沒有CPU供使用,屬於此類的任務就徹底不運行(甚至不參與對 CPU的搶奪)。爲了避免“優先級反轉”問題,SCHED_GIDLE類的進程在睡眠時(此處指內核睡眠,不是系統調用sleep造成的睡眠)會臨時提高 優先級。網絡由HTB排隊規則管理,配有一組流量控制邏輯。對硬盤來說,它們按linux的I/O調度來工作。
(假設三個進程A、B、C,優先級 爲A>B>C,假設C先運行,佔了一個重要的共享資源,A也想要這個資源,所以A等待C完成,但由於B的優先級比C高,結果C還沒完成就調度 到B運行了,這樣總的來看,B的運行先於A,儘管A的優先級比B高。這就是“優先級反轉”問題。通常的解決方法是:誰佔了重要的共享資源,誰就臨時提升自 己的優先級,比如C佔了資源後優先級臨時升到和A一樣高,釋放資源後再把優先級降回來。說白了,佔用資源的一夥人,他們最好有相同的優先級,不然會有麻 煩)

除了這些,google還有很多代碼用於監控。監控所有的硬盤和網絡流量,記錄之,用於後期對運維的分析。google在內核加了很多鉤子,這樣 他們就能把所有的硬盤I/O情況返回給應用程序——包括異步的寫回I/O。當Mike被問到他們是否使用跟蹤點時,回答是“是的”,但是,自然 的,google使用的是自己的一套跟蹤方法。

google內核改進在2010年還有很多重要的目標:

      google對CPU限制功能很興奮,通過此功能,就能給“低延時任務”較高的優先級,而不必擔心這些任務把霸佔整個系統。

      基於RPC的CPU任務調度,這包括監控RPC入口流量,以決定喚醒哪一個進程。(這很有分佈式OS的味道)

      延遲調度。對很多任務來說,延遲並不是什麼大不了的事。但當RPC消息到來時,內核卻嘗試去運行所有這些任務;這些消息不會分佈到不同的CPU上(意思就是處理這些請求的服務進程可能就在某幾個CPU上運轉),這造成了系統負載在CPU間分配的問題。所以任務應該能被標爲“延遲調度”;當被喚醒後,這些任務並不會被直接放到運行隊列上,而是等待,知道全局的CPU負載調度完成。

      插入空閒週期。高級電源管理使google能夠把服務器用到接近燒燬的邊緣——但是不超過這個邊緣。

      更好的內存管理已經列入計劃,包括統計內核的內存使用。

      “離線內存”。Mike強調想買到便宜好用的內存是越來越難。所以google需要能夠把壞內存標出的功能。HWPOISON興許可以幫到他們。

      在網絡方面,google希望改進對“接收端縮放”的支持——即把輸入流量導到指定的隊列。google還需要統計軟件中斷次數然後轉給指定的任務——網絡進程通常包含大量的軟中斷。google已經在擁塞控制上做了很多工作;他們開發了“網絡不安全”的擁塞算法,該算法在google的數據中心運轉良好。名爲“TCP pacing”的算法放慢了服務器的輸出流量,避免了交換機過載。
      (自己管理數據中心的公司就是不一樣,網絡優化做得很細)

      在存儲方面,google花了大量精力降低塊設備層的瓶頸,這樣就能更好的使用高速flash。在塊設備層通過flash來提高存儲效率已經列入了開發計劃。google考慮在內核裏增加flash轉換層,但大家建議google還是把操作flash的邏輯直接放入文件系統層更好一些。

Mike最後總結了幾個“感興趣的問題”。其中一個是google希望把文件系統的元數據固定在內存裏。目的是減少I/O請求的時間。從硬盤讀取一個塊的時間是已知的,但是如果元數據不在內存中,就會有不只一個I/O操作被執行(會有新的I/O操作用來讀元數據)。這樣就減慢了讀文件的速度。google目前對此問題的解決方案是直接從原始塊設備讀取數據到用戶空間(估計是用O_DIRECT,然後自己在用戶態管理元數據緩存,這樣就不會使用系統的cache),但以後不想 再這麼做了。
(不知道google所說的filesystem metadata到底指哪些數據,因爲不同的文件系統,metadata也很不同,既然google說要把這些數據固定在內存裏,估計應該不大,那自己緩存有什麼不好?希望有機會可以問問Mike)

還有一個問題,使用fadvise會降低系統調用的性能。目前還不清楚問題的細節。

google的這個演講很成功,linux社區也從自己最大的客戶那裏學到了不少東西。如果google更加面向linux社區的計劃能夠付諸行動,那linux將會擁有一個更好的kernel。

(注:google可算是IT公司中使用linux最多的,也很可能是使用得最深的,30個人的內核開發隊伍,非常可觀。看看國內,很少公司、很少人爲開源做過貢獻,唉,說起來慚愧,在下也是之一啊。)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章