| RFC-0201:回收客體 VM 記憶體 | |
|---|---|
| 狀態 | 已接受 |
| 區域 |
|
| 說明 | 允許主機使用先前分配給訪客 VM 的記憶體,以及稍後釋出的記憶體 |
| 問題 | |
| Gerrit 變更 | |
| 作者 | |
| 審查人員 | |
| 提交日期 (年-月-日) | 2022-12-15 |
| 審查日期 (年-月-日) | 2022-12-01 |
摘要
允許主機回收訪客使用的記憶體。
提振精神
在訪客中執行耗用大量記憶體的應用程式,並在主機中啟動耗用大量記憶體的應用程式,即使訪客記憶體不再使用,也可能導致 OOM。
原因有二。
- 目前我們不允許主辦人自動擷取訪客的記憶內容。
- 我們不支援訪客主動告知主機「這是未使用的記憶體頁面清單,需要時請隨意使用」的方式。
使用者歷程範例
- 啟動 Termina 或 Debian 訪客
- 在訪客中啟動耗用大量記憶體的應用程式
- 在訪客中結束耗用大量記憶體的應用程式
- 在主機中啟動耗用大量記憶體的應用程式
- 觀察主機是否發生 OOM 💥
背景
作業系統啟動時,會詢問硬體 (如果是訪客,則為 Hypervisor) 有多少實體記憶體。如果主機告知訪客有 4GiB 的 RAM,訪客就會知道可以分配大約一百萬個 4KiB 頁面。
方法是在客體 OS 視為實體位址 (稱為客體實體位址) 與實際實體位址 (稱為主機實體位址) 之間,導入對應層級。提醒您,第一層的位址轉譯是訪客虛擬記憶體位址與訪客實體位址之間的對應。換句話說,訪客虛擬位址會先由硬體轉換為訪客實體位址,而硬體會使用訪客 OS 管理的頁面表格進行轉換,然後再轉換為主機實體位址。後者轉換作業是由管理程序管理的頁面表格控管。
當存取尚未對應的客體虛擬位址至客體實體位址時,客體會自行處理發生的頁面錯誤。管理程序會處理客體實體到主機實體的翻譯頁面錯誤。
我們使用分頁記憶體,也就是說,當管理程序提供 X GiB 的 RAM 給客層時,不會預先分配任何記憶體,只會在實際需要這些頁面時才分配。這裡的「必要」是指訪客嘗試存取該頁面。從管理程序的角度來看,已分配的實體記憶體頁面屬於訪客,無法用於主機程序。
因此,訪客可能會分配到大量未使用的實體記憶體頁面,而主機可能記憶體不足,無法執行自己的程序。
下文將說明如何透過 2 種方式,讓主機存取訪客記憶體:
- 在訪客中膨脹 virtio 氣球
- 在 virtio balloon 中使用免費頁面報表
Virtio-balloon
主機可以設定目標氣球大小,告知訪客 virtio-balloon 驅動程式庫將氣球 inflate 為特定大小。氣球膨脹表示訪客會保留所需數量的記憶體頁面,並將已分配記憶體頁面的訪客實體位址回報給主機。從這個時間點開始,主機可以取消認可回報的記憶體頁面,並使用支援回報記憶體的實體記憶體。
如果 virtio-balloon 協商 VIRTIO_BALLOON_F_DEFLATE_ON_OOM,訪客隨時可以再次使用記憶體。請參閱 Virtio 規格 5.5.6.1。目前我們啟用 VIRTIO_BALLOON_F_DEFLATE_ON_OOM。
主辦人可以縮小氣球的目標大小,允許訪客重複使用氣球中的頁面。如果設定的氣球大小小於氣球中的實際頁數,訪客可以重複使用先前提供給氣球的頁面。如果訪客想再次使用記憶體,系統會deflate氣球,讓主機知道訪客日後會使用一系列實體訪客位址。在從氣球移除訪客存取頁面後,如果發生縮減,就會發生訪客實體到主機實體頁面錯誤,而管理程序會為訪客分配新的實體記憶體頁面。
如要詳細瞭解 virtio-balloon 的核心功能,請參閱 Virtio Balloon 投影片和 Virtio Balloon 影片。
免費網頁報表
2020 年,virtio-ballon 收到一項名為「免費頁面報告」的新功能。
免費頁面回報功能可讓訪客向主機回報免費記憶體頁面。訪客會將 4 MiB 大小的可用頁面 (Linux 實作常數) 新增至可用頁面報告,然後將報告傳送給主機。在主機確認檢舉前,房客保證不會重複使用任何免費頁面。
主機收到免費頁面報告時,會取消記憶體頁面的認可,讓主機應用程式可以使用這些頁面,並將報告確認傳回給訪客。此時,訪客可能會重複使用先前釋放並確認的頁面。如果訪客決定重複使用該頁面,主機會偵測到訪客實體到主機實體頁面錯誤,並分配新的實體頁面來滿足訪客要求。
如需詳細說明,請參閱免費頁面回報:作者 Alexander Duyck ( Intel)。投影片 10。
利害關係人
協助人員:
- cpu@google.com
審查者:
- abdulla@google.com
- dahastin@google.com
- tjdetwiler@google.com
已諮詢:
- cwd@google.com
社交:
這項 RFC 已通過虛擬化團隊的審查。我們與 cwd@google.com 討論了這個方法,他正在為 ChromeOS 解決類似但規模更大的問題。
設計
目標
- 在訪客中執行應用程式後,回收主機的記憶體。
- 盡量減少記憶體回收對訪客和主機效能的影響。
Non-Goal
- 在多個客層之間平衡記憶體用量。
- 在訪客和主機爭用記憶體時,動態調整應用程式的優先順序。
- 支援 Fuchsia 客戶端的記憶體回收。
成功標準
- 在「動機」一節所述的使用者歷程中,Fuchsia 不會發生 OOM 錯誤。
- 主機的可用記憶體會恢復到執行耗用大量記憶體的客體應用程式之前。
- 記憶體回收前後,訪客都可以繼續執行耗用大量記憶體的應用程式。
- 除非主機記憶體壓力偏低,否則訪客頁面快取不會受到影響。
- 當至少有一位訪客正在執行時,主機 OOM 的數量大幅減少。
愜意
- 使用 virtio_balloon 中的免費頁面回報功能,回收可用記憶體供主機使用。
- 在 LOW 和 CRITICAL 主機記憶體壓力事件中,膨脹氣球會清除訪客頁面快取,並回收分散的記憶體頁面。
- 概念驗證已確認免費頁面報表確實會如預期回收記憶體。
實作
使用免費網頁報表
我們會使用「釋放頁面回報」功能,向主機回報並回收所有可用記憶體。
所有項目都必須是 PAGE_REPORTING_MIN_ORDER 以上的順序 (在 Linux 核心中定義為 4MiB)。
使用免費網頁報告後,系統會在接下來 30 秒內回收大部分記憶體。如果回報的可用頁面大小為 2MiB 或 4MiB,則預期會出現一定程度的記憶體片段化。為盡量減少對成效的影響,系統會逐步為房客提供免費頁面報表。
Linux-5.15 會以 2MiB 和 4MiB 區塊回報 30 秒內的大部分可用記憶體。
免費頁面報表不會清除 Linux 頁面快取,如果訪客執行大量 IO 工作負載,可能會造成問題。如要瞭解 Linux 中的頁面快取,請參閱「Linux 頁面快取基礎知識」。
日後 Linux 客戶端映像檔開始使用 MGLRU 時,這項設定可能會變更。請參閱 MGLRU 的「缺點、替代方案和未知」一節。
任意捨棄網頁快取並非好事,因為快取有其存在意義。主機應只在實際需要時,才從訪客頁面快取中取得記憶體。也就是說,當主機記憶體不足時,我們需要提供方法,回收用於頁面快取的訪客記憶體。
在主機記憶體壓力下膨脹客體氣球
第二項變更則是使用記憶體壓力供應器,在 WARNING 和 CRITICAL 主機記憶體層級上膨脹氣球。
吹氣球可達成兩項目標:
- 清除訪客頁面快取,這對訪客執行大量檔案 I/O 並填滿頁面快取時非常重要。
- 回收大部分的記憶體片段頁面,因為氣球膨脹是以 4KiB 粒度完成,而可用頁面回報則使用 4MiB。
膨脹量會與可用的訪客記憶體成正比。在 WARNING 和 CRITICAL 主機記憶體事件中,氣球會膨脹至可用客體記憶體的 90%。如果可用記憶體從 NORMAL 快速降至 CRITICAL,我們就必須在 WARNING 和 CRITICAL 事件中擴充記憶體。主機記憶體壓力恢復正常時,氣球會縮小至 0%。
我們希望避免在主機記憶體壓力過大時,不斷膨脹和縮減氣球。氣球充氣會對來賓和主辦人造成效能負擔。根據 Intel 的說法,除了上述問題之外,氣球大小不斷變更也會導致許多 TLB 停用。
為避免氣球大小來回跳動,我們會將氣球充氣作業限制為每 X 秒充氣一次。X,以便在團隊食品測試期間設定。初始值為 1 分鐘。如果主機長時間處於記憶體壓力警告狀態,可能會發生更多逾時情況,例如氣球壓縮逾時。您可以根據 teamfood 測試遙測資料新增其他逾時。
效能
實作記憶體回收功能後,使用者在訪客中執行耗用大量記憶體的應用程式時,主機記憶體效能就會提升。主機可用的記憶體會變多,不必再使用記憶體壓縮和其他耗用 CPU 的方式來取得記憶體,而客機會有可回收的記憶體。
Linux 實作作業中的免費頁面報表作業會間隔 30 秒,以減少對訪客的效能影響。預計記憶體密集型客體工作負載的效能會受到 1% 到 2% 的影響。請參閱免費網頁報表基準。
主機記憶體不足時,膨脹氣球可能會增加主機和訪客的額外負載。
我們需要測量主機在記憶體壓力下運作時,啟用和停用記憶體回收功能時的訪客「TLB shootdown」中斷次數。
基準:
- Linux 壓力測試工具
- 其中一個圖形基準測試,例如 Uningine
要擷取的指標
- 基準回報的一般指標,用於偵測效能衰退
- 基準測試前後,訪客和主機的可用記憶體
- 客層中的 TLB 射擊中斷
安全性考量
回收的免費頁面會在取消認可作業中歸零,與氣球膨脹作業相同。這樣可避免房東和其他房客看到訪客資訊。
測試
大部分工作將由單元測試和 2 項整合測試完成。其中一項整合測試會涵蓋免費網頁回報記憶體回收,另一項則會涵蓋訪客網頁快取和氣球膨脹的互動。
動機一節所述的使用者歷程將手動測試。 使用者歷程依賴訪客啟動,因此不具密封性。如果我們有自動化端對端虛擬化測試,就可以擴大測試範圍,涵蓋這個情境。我們認為,針對這項 RFC 建立自動化端對端虛擬化測試,並不可行。
缺點、替代方案和未知事項
多代 LRU 架構
多代 LRU 架構 (又稱 MGLRU) 是 Linux 核心的記憶體改善功能。就 CPU 使用率而言,Linux 目前的頁面回收成本過高,且經常無法正確選擇要清除的內容。MGLRU 的目標是做出比現有 Linux 核心頁面回收程式碼更明智的選擇,並以更高的效率完成這項工作。根據 Google 工程師的數據,冷啟動時間最多可減少 16%,同時減少低記憶體終止作業次數;ChromeOS 的記憶體不足終止作業次數減少了 59% 以上,瀏覽器中低記憶體分頁遭捨棄的次數也減少了 96%,伺服器結果也十分理想。
詳情請參閱 PATCH v14 00/14 Multi-Gen LRU Framework。
我們目前使用的 Termina 5.15 沒有 MGLRU 修補程式。上游不提供 MGLRU。Termina 核心開發人員正在等待 MGLRU 獲上游接受,以便將其回溯移植至 Termina 5.15
MGLRU API 可用於驅動免費網頁的報表邏輯。建議您調查使用 MGLRU API 的情況,以提升 Linux 核心中的可用頁面回報效能。如果成功,這項變更可提議合併至上游。這項最佳化作業會針對 Linux 核心中現有的免費頁面報表解決方案進行。
主機回收客體記憶體時,不需要依附 MGLRU。
持續調整氣球大小的替代做法
最初建議的記憶體回收方式,因此稱為記憶體精靈。
ChromeOS 目前就是採用這種方法。但也有許多缺點
- 必須選擇輪詢時間間隔。
- 據 Intel 回報,即使是小幅調整氣球大小,也會造成效能負擔。請參閱「Constant balloon resizes cause many TLB shootdowns」。
- 如要讓這項功能正常運作,氣球必須一直膨脹到約 90% 的訪客記憶體。
- 客層應用程式可以快速分配,並在下一個輪詢間隔之前遭 OOM 精靈終止
ChromeOS 方法
ChromeOS 目前正在開發下一代回應式 virtio-balloon。簡單來說,這個概念是在訪客和主機中都使用記憶體不足終止工具,調整氣球大小,而不是終止應用程式。此外,我們也計畫使用 MGLRU 指導氣球大小調整邏輯。
ChromeOS 解決的問題難度更高,也與眾不同:
- ChromeOS 有多位訪客和主機,所有使用者都會爭用記憶體
- ChromeOS 和所有訪客都有 MGLRU 和記憶體不足終止工具 Daemon,可供連結。
- 為所有工作負載選擇合適的氣球大小是難題。
- 我們必須定義一組經驗法則,引導氣球充氣/放氣邏輯
- 請務必取得裝置機群的資料,以便建構啟發式方法並分析其成效。
- 更重要的是,如果您使用 LMKD 觸發氣球充氣/放氣,就必須快速調整氣球大小,否則 OOM killer 會在氣球充氣/放氣時終止應用程式
Fuchsia 虛擬化沒有大量裝置可供收集統計資料,我們想解決的問題簡單得多。Fuchsia 沒有可連結的 OOM killer。
Fuchsia 主機可同時執行多個客體 (Termina、Debian、Fuchsia)。目前這並非主要用途,使用者和測試通常會執行單一客體。一旦開始使用效能更強大的硬體,情況可能會有所不同。如果訪客未使用所有可用記憶體,建議解決方案可適用於多個超額訂閱的訪客。例如閒置的 Debian 客戶端和作用中的 Termina 客戶端。
如果我們必須支援多個訪客,且這些訪客會嘗試使用所有可用記憶體,問題空間就會變得更大。決定哪個訪客應用程式或哪個訪客更重要,應是產品政策。我們應著重於向產品公開合適的工具,但在平台層級,我們不希望對低記憶體的處理方式做出規定。
我們會採用較簡單且可預測的解決方案來解決目前的問題,同時新增資料收集功能,分析 OOM,並判斷是否需要新增更複雜的啟發式方法。
透過 DAX 和 virtio-fs 共用主機和訪客頁面快取
DAX 對應可讓訪客直接從主機快取存取檔案內容,因此可避免訪客與主機之間重複。新增支援 DAX 的 virtio-fs,可啟用頁面快取共用功能,並在記憶體壓力過大時捨棄頁面快取,這是 virtio 氣球膨脹的替代解決方案,可清除訪客頁面快取。由於氣球膨脹,精細的頁面快取控制項會比全面頁面快取逐出作業更合適。我們可以捨棄舊的頁面快取,同時保留新的頁面快取,以減輕記憶體壓力,同時不會對主機/訪客效能造成太大影響。