1. 程式人生 > >圖解VMware記憶體機制

圖解VMware記憶體機制

source:  在寫《VMware記憶體機制初探》之後,原本是計劃寫一篇《VMware記憶體機制再探》的,講一講VMware記憶體機制中的另外幾個重要內容,比如透明記憶體共享(TPS, Transparent Page Sharing), Relaim Memory, Ballooning, swapping等等。但有網友反映說前面的文章還是不好懂。於是想,如果如同官方文件那樣條條框框地列出來,那還不如大家都去看原版手冊呢,所以有了這麼一篇東西。
首先,大家要記住,在記憶體沒有過量配置(Memory Overcommitment)的情況下,記憶體的排程機制完全不會啟動,就沒有Reclaim記憶體。很明顯嘛,主機總的實體記憶體(Host Physical Memory)大於所有虛機配置記憶體的總額的情況下,每臺虛機想要多少記憶體,都能得到滿足,當然不需要排程。
所以,以下探討的VMware的記憶體機制,都是在記憶體過量配置的情況下發生的。
我的故事發生在一個有智慧的水池(Host)中,水池有不少水(4GB實體記憶體),裡面還有2個水箱(配置了2臺VM),水箱有一定的容量(配置記憶體是4GB),原本是空的(沒有開機)。
snap0049

但是現在水箱1裡面要養魚了,必須放點水進去以便魚可以存活(開機了)。最少需要1GB記憶體。於是水箱1(VM1)就向水池(Host)要水(實體記憶體),水池裡面有足夠的水,就滿足了水箱1的要求。現在水箱1有1GB的活水,而水池裡面只剩下3GB的水了。 snap0050 現在我們又向水箱1裡面多丟了些魚(啟動新的應用),原來1GB的水不夠用了,於是水箱1就繼續向水池要水,水池裡面還有足夠的水,就又滿足了水箱1的要求。現在水箱1裡面有3GB的水,而水池裡面只剩下1GB的水了。


解釋:要注意的是,此時VM1裡面的應用程式都是活動的(active),所以這些記憶體都屬於活躍狀態,叫做活動記憶體(Active Memory)。
snap0051 經過了一段時間以後,水箱1裡面的魚被捕走了,現在水箱1不需要那麼多水也足夠養活剩下的魚了。但是水池並不知道水箱1的狀況。於是水箱1還是有那麼多水。
解釋:
VM1的某些應用結束後,釋放了部分記憶體,但是這些記憶體釋放動作是在VM的Guest OS層面釋放的,因此Host並不知道有記憶體被釋放了,這些記憶體沒有歸還Host,仍然由VM1霸佔著。VM1中就有一部分記憶體屬於idle,另外一些正在使用的記憶體就是active memory。當然,就VM1自己的GOS看起來,有3GB空閒記憶體(idle memory),1GB的活動記憶體;而此時就Host看來,只看見有3GB記憶體是分配給了VM1的。Host通過VMware Tools中的驅動,每隔一定的時間(ESX4中預設是60秒,ESX3中預設是30秒)去掃描一下VM1的記憶體使用狀態,以便了解它到底有多少活動記憶體(active memory)

snap0052 此時,我們開始在水箱2中養魚了(VM2開機),水箱2也開始從水池中抽水。但是水池裡面的水不能枯竭,因此水池有警戒水位,第一條警戒水位是6%,當下降到第一警戒水位以下並仍然在不停下降時,就要開動其他機制從其他水箱反抽水。
解釋:
VM2開機時也需要1GB記憶體,在啟動時,它也不斷向Host請求記憶體。Host則將自己的記憶體源源不斷地分配給VM2,直到下降到第一條警戒位6%。Host記憶體有4種狀態,分別是High, Soft, Hard和Low,它們間的分界線分別是6%, 4%, 2%和1%。可用記憶體高於6%時,不會啟動Balloon或Swap機制。當低於6%並往4%逼近的時候(soft狀態),Balloon機制就啟動了。(關於記憶體的4種狀態的更多解釋,請參閱官方文件《Understanding Memory Resource Management in VMware ESX Server》。如何檢視這4種狀態?可以用esxtop或者resxtop)
image 那到底向哪個水箱抽水呢?誰的水最富裕就向誰抽。
解釋:
如何判斷呢?剛才我們說過,Host每隔一定時間就會掃描Guest OS的記憶體使用狀況,此時,Host會計算每個VM的份額記憶體比ρρ和VM的空閒記憶體還有空閒記憶體稅(IMT, Idel Memory Tax)密切相關,對ρ最小的那臺虛機啟動氣球驅動(balloon driver),氣球開始膨脹(inflating)。關於ρ和IMT的演算法,請參見本人博文《空閒記憶體稅的演算法》。
snap0054 於是,氣球開始膨脹,並將多餘的水擠出水箱。
解釋:Balloon驅動如同普通驅動那樣,不斷向Guest OS索取記憶體,Guest OS儘自己可能滿足氣球驅動,並優先將空閒部分的記憶體分配給它,注意,此時可能出現Guest OS自己的實體記憶體不足,並引起Guest OS的paging機制,將一部分記憶體page out到自己的swap中。這個例子中,VM1還有很多空閒記憶體,因此足夠讓主機回收並滿足VM2的需求。

主機將比較氣球膨脹獲得的這部分記憶體的地址,如果原先是分配給VM1獨享的,(也就是沒有TPS共享),那麼就可以收回。主機將不停的通過氣球驅動收回記憶體,收回的目標是保持至少6%的記憶體。這個回收記憶體的過程就叫Reclaim。

注意:此時記憶體沒有出現爭用情況,因此shares仍然沒有起作用,但是Overcommitment是存在的,所以會有reclaim,會有ballooning。
snap0056 Ballooning回收記憶體是比較慢的,通常需要幾分鐘。
如果主機可用記憶體池的記憶體減少速度大於氣球驅動返還主機的記憶體,那麼可用記憶體會進一步下降,當突破4%的第2警戒線時,進入到hard狀態,主機就會啟用第2種reclaim機制——swapping,將VM1的一部分實體記憶體交換到swap檔案中,以加快回收記憶體的速度。目的是將可用記憶體保持在4%的警戒線以上。

如果可用記憶體繼續下降到2%以下,進入到low狀態的時候,ESX不僅會繼續加速Swapping,還會阻止其上所有VM的記憶體請求。

現在,情況又發生了變化,水箱2中的魚越來越多了,它不停地向水池要水,而水池也通過氣球驅動,不停地將水箱1中的空閒記憶體擠出來,直到水箱1和2的總需求量大於了水池能供給的水量。水池再也不能提供更多的水了,只能部分滿足2個水箱的要求了。不夠的部分怎麼辦?用一些髒水(swap)來滿足。髒水雖然髒(swap記憶體速度很慢),魚在髒水裡面生存的很困難,但畢竟還是有水的,不至於因為沒有足夠的水而導致魚死掉。 snap0058
此時,VM1和VM2的active memory由2部分組成,1部分是獲得的主機實體記憶體,另一部分是swap。請注意,Guest OS是不知道自己的一部分實體記憶體是硬碟上的swap檔案的。

當機器記憶體不足競爭開始的時候,shares開始起作用。但是,請注意,如果IMT是0,對空閒記憶體不徵稅,由於4GB的VM1和4GB的VM2的份額都是40960,因此它們最終會拿到相同的實體記憶體2GB。但是如果IMT是預設值,那麼空閒記憶體的代價更大,那麼這2臺VM會根據active記憶體數量的不同,獲得不同數量的實體記憶體。
【本文的知識要點回顧】
(1) 在記憶體沒有過量配置(Memory Overcommitment)的情況下,不需要Reclaim記憶體
(2) 什麼時候開始Reclaim記憶體?當突破6%的警戒線,記憶體狀態從High變成了Soft的時候
(3) Reclaim優先用Ballooning,只有Ballooning不夠用的時候,才會用Swapping
(4) 什麼時候開始swapping? 當主機可用記憶體跌破4%警戒線,記憶體狀態變成Hard的時候
(5) Host無法知道VM內的哪些記憶體塊已經處於空閒(idle)狀態。必須用Ballooning才能收回空閒記憶體。
(6) 儘量避免資源爭用,否則造成的Chasing-the-tail效應,會導致更嚴重的效能負面影響。
【參考文件】