RFC-0201:收回訪客 VM 記憶體

RFC-0201:回收訪客 VM 記憶體
狀態已接受
區域
  • 虛擬化
說明

允許主機使用先前分配給訪客 VM 的記憶體,以及稍後釋出的記憶體

問題
Gerrit 變更
作者
審查人員
提交日期 (年-月-日)2022-12-15
審查日期 (年-月-日)2022-12-01

摘要

允許主機回收訪客使用的記憶體。

提振精神

在訪客中執行耗用大量記憶體的應用程式,並在主機中啟動耗用大量記憶體的應用程式,即使訪客記憶體不再使用,也可能導致 OOM。

原因有二。

  1. 目前我們不允許主辦人自動擷取訪客的記憶內容。
  2. 我們不支援訪客主動告知主機「這是未使用的記憶體頁面清單,需要時請隨意使用」的方式。

使用者歷程範例

  1. 啟動 Termina 或 Debian 訪客
  2. 在訪客中啟動耗用大量記憶體的應用程式
  3. 在訪客中結束耗用大量記憶體的應用程式
  4. 在主機中啟動耗用大量記憶體的應用程式
  5. 觀察主機是否達到 OOM 💥

背景

作業系統啟動時,會向硬體 (如果是訪客,則是 Hypervisor) 詢問實體記憶體容量。如果主機告知訪客有 4GiB 的 RAM,訪客就會知道可以分配大約一百萬個 4KiB 頁面。

方法是在客體 OS 視為實體位址 (稱為客體實體位址) 與實際實體位址 (稱為主機實體位址) 之間,導入對應層級。提醒您,第一層的位址轉譯是訪客虛擬記憶體位址與訪客實體位址之間的對應。換句話說,訪客虛擬位址會先由硬體轉換為訪客實體位址,而硬體會使用訪客 OS 管理的頁面表格進行轉換,然後再轉換為主機實體位址。後者轉換作業是由管理程序管理的頁面表格控管。

當存取尚未對應的客體虛擬位址至客體實體位址時,客體會自行處理發生的頁面錯誤。管理程序會處理客體實體到主機實體的翻譯頁面錯誤。

我們使用分頁記憶體,也就是說,當管理程序提供 X GiB 的 RAM 給客層時,不會預先分配任何記憶體,只會在實際需要這些頁面時才分配。這裡的「必要」是指訪客嘗試存取該頁面。從管理程序的角度來看,已分配的實體記憶體頁面屬於訪客,無法用於主機程序。

因此,訪客可能會分配到大量未使用的實體記憶體頁面,而主機可能記憶體不足,無法執行自己的程序。

下文將說明如何透過 2 種方式,讓主機使用訪客記憶體:

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 收到一項名為「免費頁面報告」的新功能。

房客可透過免費頁面回報功能,將免費記憶體頁面回報給主機。訪客會將 4MiB 大小的可用頁面 (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 中的免費頁面回報功能,回收可用記憶體供主機使用。
  • 在「低」和「嚴重」主機記憶體壓力事件中,膨脹氣球以清除訪客網頁快取,並回收分散的記憶體頁面。
  • 概念驗證結果顯示,免費頁面報表確實會如預期回收記憶體。

實作

使用免費網頁報表

我們會使用「釋放頁面回報」功能,向主機回報並回收所有可用記憶體。

所有內容的順序都必須為 PAGE_REPORTING_MIN_ORDER 以上 (在 Linux 核心中定義為 4MiB)。

使用免費網頁報表功能後,大部分記憶體會在接下來 30 秒內回收。如果回報的可用頁面大小為 2MiB 或 4MiB,則預期會出現一定程度的記憶體片段化。為盡量減少對效能的影響,系統會錯開時間,逐步為訪客提供免費網頁報表。

Linux-5.15 會以 2MiB 和 4MiB 區塊回報 30 秒內的大部分可用記憶體。

免費頁面報表不會清除 Linux 頁面快取,如果訪客執行大量 IO 工作負載,可能會造成問題。如要瞭解 Linux 中的頁面快取,請參閱「Linux 頁面快取基礎知識」。

日後 Linux 客戶端映像檔開始使用 MGLRU 時,這項設定可能會變更。請參閱 MGLRU 的「缺點、替代方案和未知」一節。

不要任意清除網頁快取,這是好事,因為網頁快取有其存在意義。只有在實際需要時,主機才應從訪客網頁快取中取得記憶體。也就是說,當主機記憶體不足時,我們需要提供方法,回收用於頁面快取的訪客記憶體。

主機記憶體壓力過大時,擴充訪客氣球

第二項變更是在 WARNING 和 CRITICAL 主機記憶體層級,使用 memorypressure 提供者擴充氣球。

吹氣球可達成兩項目標:

  • 清除訪客頁面快取,這對訪客執行大量檔案 I/O 並填滿頁面快取時非常重要。
  • 由於氣球膨脹是以 4KiB 的精細度完成,而可用頁面回報則使用 4MiB,因此可回收大部分的記憶體片段頁面。

膨脹量會與可用的訪客記憶體成正比。在 WARNING 和 CRITICAL 主機記憶體事件中,氣球會膨脹至可用訪客記憶體的 90%。如果可用記憶體從 NORMAL 快速降至 CRITICAL,我們就必須在 WARNING 和 CRITICAL 事件中擴充記憶體。主機記憶體壓力恢復正常時,氣球會縮小至 0%。

我們希望避免在主機記憶體壓力過大時,不斷膨脹和縮減氣球。氣球膨脹會對訪客和主機造成效能負擔。根據 Intel 的說法,氣球大小不斷變化會導致許多 TLB 射擊

為避免氣球大小來回跳動,我們會將氣球膨脹作業限制為每 X 秒膨脹一次。X,在團隊食品測試期間設定。初始值為 1 分鐘。如果主機在記憶體壓力警告中停留太久,可能會發生更多逾時情況,例如氣球解壓縮逾時。您可以根據團隊 food 測試遙測資料新增其他逾時。

效能

實作記憶體回收功能後,使用者在訪客中執行耗用大量記憶體的應用程式時,主機記憶體效能就會提升。主機可用的記憶體會變多,不必再使用記憶體壓縮和其他耗用 CPU 的方式來取得記憶體,而客機會有可回收的記憶體。

Linux 實作作業會每隔 30 秒執行一次免費網頁報表作業,以減少對訪客的效能影響。我們預期記憶體密集型客體工作負載的效能會受到 1% 到 2% 的影響。請參閱免費網頁報表基準

主機記憶體不足時,膨脹氣球可能會增加主機和訪客的額外負載。

我們需要測量主機在記憶體壓力下運作時,啟用和停用記憶體回收功能時的客體「TLB shootdown」中斷次數。

基準:

要擷取的指標

  • 基準回報的一般指標,用於偵測效能衰退
  • 基準化前後,訪客和主機的可用記憶體
  • 客層中的 TLB 射擊中斷

安全性考量

回收的免費頁面會在取消認可作業中歸零,與氣球膨脹相同。這麼做可防止訪客資訊洩漏給主辦人和 其他訪客。

測試

大部分工作將由單元測試和 2 項整合測試完成。其中一項整合測試會涵蓋免費網頁報告記憶體回收,另一項則會涵蓋訪客網頁快取和氣球膨脹的互動。

我們會手動測試動機一節所述的使用者歷程。 使用者歷程依賴訪客啟動,因此不具密封性。如果我們有自動化端對端虛擬化測試,就可以擴大測試範圍,涵蓋這個情境。我們認為,針對這項 RFC 建立自動化端對端虛擬化測試,並不可行。

缺點、替代方案和未知事項

多代 LRU 架構

多代 LRU 架構 (又稱 MGLRU) 是 Linux 核心的記憶體改善功能。Linux 目前的頁面回收作業在 CPU 使用率方面成本過高,且經常會做出不當的逐出選擇。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」(氣球大小不斷調整會導致許多 TLB 射擊)
  • 如要讓這項功能正常運作,氣球必須一直膨脹到約 90% 的訪客記憶體。
  • 客層應用程式可快速分配,並在下一個輪詢間隔之前遭 OOM Daemon 終止

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 氣球膨脹的替代解決方案,可清除訪客頁面快取。由於氣球膨脹,精細的頁面快取控制項會比全面頁面快取逐出作業更合適。我們可以捨棄舊的頁面快取,同時保留新的頁面快取,以減輕記憶體壓力,同時不會對主機/訪客效能造成太大影響。

既有技術和參考資料