Hugemem Kernel Explained [轉]

zecaro發表於2011-06-14

這篇文章幾個月前就讀過,現在忘得也七七八八了。當時讀的時候是純粹的研究下,現在再讀是因為有實際需求裡面涉及到這個,雖然已經更改用了4G/4G。感覺這次讀起來更有感觸。

文章中所說的發生 out of memory ,也就是我這兒之前改成hugemem核心的原因。修改完之後,確實穩定下來了。 至於為什麼會out of memory(畢竟記憶體不大,4G,REDHAT AS3U6,ORACLE 9206 rac ,OCFS),猜測下的話,資料庫前端連線很多,smp的記憶體管理更容易耗盡低端記憶體。然後系統隨機殺程式,crash掉。


紅旗DC系列Linux作業系統(x86平臺)中帶有四類核心:

  • UP (支援單核心)
  • SMP (支援多核心)
  • hugemem
  • Icc* (用intel C編譯器編譯的核心)

其中hugemem核心往往引起很多困惑,這裡希望能一勞永逸地把hugemem解釋清楚。

Hugemem vs. SMP

x86平臺下, 紅旗DC4.1和5.0所帶的smp和hugemem核心都開啟了PAE支援,也就是說都可以支援4G以上的實體記憶體。引入hugememe核心的目的_不是_支援超過4G實體記憶體(SMP核心就可以支援了),而是更穩定地支援大記憶體x86系統(所謂大記憶體可以簡單理解為超過12G記憶體的系統)。


smp和hugemem核心的 _唯一_區別是hugemem核心中打入了4G/4G補丁,使用4G/4G補丁可以將直接對映的核心資料程式碼地址空間從1G擴大到4G,將程式的虛擬地址空間也由3G擴大到4G。當實體記憶體過多時,管理這些實體記憶體的工作本身會佔用不少寶貴的核心地址空間(所謂低端記憶體),此時雖然總的實體記憶體還有不少空閒,由於低端記憶體耗盡,也可能會導致記憶體緊張,觸發OOM (Out of memory) killer,導致應用終止甚至核心崩潰。


如果超過12G實體記憶體,一般建議使用hugemem核心。不過,hugemem會帶來一定的效能損失。


以上說明對於一般使用者應該足夠了,如果想了解4G/4G補丁的更多細節,請繼續往下看...


大記憶體x86系統帶來的問題


4G/4G補丁主要應用於大記憶體x86系統(所謂大記憶體可以簡單理解為超過12G記憶體的系統),這樣的系統往往需要更多的核心地址空間和使用者地址空間。


在x86架構下,我們知道虛擬地址空間的大小為4G。在這4G空間中,使用者空間佔3G (0x00000000到0xbfffffff),核心空間佔1G(0xc0000000到0xffffffff)。這樣的分配策略成為3G/1G分配。這種分配方式對於擁有1G實體記憶體以下的系統是沒有任何問題的,即使超過1G實體記憶體,3G/1G分配策略也沒有什麼問題,因為核心可以在高階記憶體區域 (實體地址1G以上的記憶體)中存放一些核心資料結構(比如頁緩衝等)。然而,隨著實體記憶體的增多,3G/1G分配策略的問題也逐漸會暴露出來。這是因為一些關鍵的核心資料結構(比如用於管理實體記憶體的mem_map[])是存放在1G核心空間之內的。對於32G記憶體的系統,mem_map[]會佔用近 0.5G的低端記憶體(實體地址896M以下的記憶體),這樣留給核心其他部分的記憶體就不到所有記憶體的1.5%;而對於64G記憶體的系統,mem_map[] 本身就會耗盡所有的低端記憶體,造成系統無法啟動。把mem_map[]放到高階記憶體的做法也不太實際,因為mem_map[]和記憶體管理,體系結構相關底層實現,檔案系統以及驅動等幾乎所有的核心的關鍵部分均有聯絡。


4G/4G的作用


與3G/1G不同,4G/4G分配方式可以使核心空間由1G增加到4G,而使用者空間也由3G增加到4G。從 /proc/PID/maps 檔案中可以直觀地看到4G/4G所起的作用:


00e80000-00faf000 r-xp 00000000 03:01 175909 /lib/tls/libc-2.3.2.so

00faf000-00fb2000 rw-p 0012f000 03:01 175909 /lib/tls/libc-2.3.2.so

[...]

feffe000-ff000000 rwxp fffff000 00:00 0


從上面的maps可以看出,堆疊的棧底地址為0xff000000 (4GB 減去 16MB)。


從/proc/maps中則可以看到核心擁有了4G大小的低端記憶體,即使對於64G實體記憶體的系統,也有3.1G低端記憶體可供使用:


MemTotal: 66052020 kB

MemFree: 65958260 kB

HighTotal: 62914556 kB

HighFree: 62853140 kB

LowTotal: 3137464 kB

LowFree: 3105120 kB


相比3G/1G分配策略,對於4G實體記憶體系統,使用4G/4G分配可以增加低端記憶體達3倍以上,而對於32G實體記憶體系統,則會有更多的提升,達到原來的6倍。 理論上,4G/4G策略可以支援實體記憶體達200G的x86系統(如果硬體沒有限制的話),即使對於這樣的系統,4G/4G策略也能保證留有1G可用的低端記憶體。


4G/4G的代價


天下沒有免費的午餐,4G/4G也是如此。4G/4G透過完全分離使用者空間和核心空間的地址對映來增加低端記憶體,這樣做會帶來一些效能損失,具體而言,當發生上下文切換的時候(比如程式呼叫系統呼叫或者發生中斷),必須重新裝載頁表(3G/1G策略下不需要載入,因為核心可以直接“借用”每個程式的頁表進行記憶體對映),頁表的重新裝載後必須清空TLB(否則的話TLB中記錄的對映就和新的頁表不一致了),而清空TLB是一個很費時的操作,原先快取於TLB中的“舊”的對映會被丟掉,這一損失到還在其次(因為不經TLB直接從CPU快取中讀取頁表也並不會有太大延遲),最大的損失在於清空TLB(透過操作%cr3)這個操作本身代價很高。


何時使用(or不使用)4G/4G?

對於這個問題,沒有放之四海而皆準的答案。只有一些拇指定律。一般情況下,超過16G記憶體幾乎肯定需要使用4G/4G (除非執行的應用負載很輕,不過大記憶體系統很少有負載輕的情況),如果負載很重(不如執行資料庫進行著大量I/O操作),那麼12G以上的系統就應考慮使用4G/4G。也可以透過觀察空閒低端記憶體大小來大體判斷一下(/proc/meminfo),如果空閒低端記憶體(LowFree)小於100M,那麼就可以考慮使用4G/4G了。8G以下的系統一般不必使用4G/4G。


需要指出的是,如果需要大記憶體,最好的解決方法是用64位系統,而不是使用4G/4G。


Hugemem vs. SMP (revisited)

現在再來看hugemem是否感覺不一樣了?


x86平臺下, 紅旗DC4.1和5.0所帶的smp和hugemem核心都開啟了PAE支援,也就是說都可以支援4G以上的實體記憶體。引入hugememe核心的目的_不是_支援超過4G實體記憶體(SMP核心就可以支援了),而是更穩定地支援大記憶體x86系統(所謂大記憶體可以簡單理解為超過12G記憶體的系統)。


smp和hugemem核心的 _唯一_區別是hugemem 核心中打入了4G/4G補丁,這樣,可以直接對映的核心資料程式碼地址空間從1G擴大到4G,程式的的虛擬地址空間也由3G擴大到 4G。當實體記憶體過多時,管理這些記憶體本身會佔用不少寶貴的核心地址空間(所謂低端記憶體),此時雖然實體記憶體還夠用,由於低端記憶體耗盡,也可能會導致記憶體緊張,觸發OOM (Out of memory) killer,導致系統不穩定。


如果超過12G實體記憶體,一般建議使用hugemem核心。不過,hugemem會帶來一定的效能損失。


作為讀了以上這許多細節的bonus,其實hugemem和SMP還有一點區別:hugemem核心中有更多的所謂"unsupported"驅動 (DC4.1下的hugemem中所不支援的驅動要比SMP多出102個),這些驅動(比如qla1280)雖然(理論上)可以工作,但並沒有在 hugemem核心下進行過驗證,所以被打入到"unsupported"一族,言外之意是如果用這些驅動如果出了問題,紅旗(理論上)是不予支援的。可以透過安裝unsupported核心驅動包進行驅動。

參考資料:

  • Patch: 4G/4G split on x86, 64 GB RAM (and more) support
  • Linux Kernel 2.6 Features in Red Hat Enterprise Linux



原文見:


作者:

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/23650854/viewspace-697938/,如需轉載,請註明出處,否則將追究法律責任。

相關文章