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

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

允許主機使用先前分配和已到期的訪客 VM 記憶體

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

摘要

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

提振精神

在訪客中執行記憶體飢餓的應用程式,並在主機中啟動飢餓的應用程式,即使已不再使用訪客記憶體,也可能引發 OOM。

這麼做有兩大好處。

  1. 我們目前不允許主機自動從訪客獲取記憶體。
  2. 我們不支援讓訪客主動告知主機「這是未使用的記憶體頁面清單,如有需要,也可使用這些頁面」。

使用者歷程範例

  1. 啟動約期訪客或債務訪客
  2. 在訪客中啟動一個飢餓的應用程式
  3. 在訪客中結束記憶體飢餓應用程式
  4. 在主機中啟動飢餓應用程式
  5. 請觀察主持人打到 OOM 次數 📷?

背景

OS 啟動時會要求硬體 (在訪客中為管理程序) 有多少實體記憶體。如果主機向訪客告知訪客擁有 4 GiB 的 RAM,訪客就會知道它可以分配一百萬或相當於 4KiB 的頁面。

這種做法的做法是,在訪客 OS 視為實際地址 (稱為訪客實際地址) 和實際實際地址 (稱為主機實際地址) 之間導入對應層級。提醒您,第一層地址轉譯是在訪客虛擬記憶體位址與訪客實際位址之間進行對應。也就是說,訪客虛擬位址會先由硬體轉譯為訪客實體位址,也就是使用訪客 OS 管理的頁面資料表進行翻譯,然後再轉譯到主機實體位址,後者則是由管理程序管理的頁面資料表控制。

訪客會處理自身的頁面錯誤,因為存取訪客虛擬位置到尚未對應的訪客實體位址時發生。管理程序會處理頁面錯誤,讓訪客實體轉譯到主機實體翻譯。

我們使用分頁記憶體,這表示當管理程序給 RAM 的訪客 X GiB 時,系統不會預先分配任何記憶體,而是只有在實際需要這些網頁時才會分配。在這種情況下,這是必要項目,表示訪客嘗試存取頁面。從管理程序的觀點來看,分配的實體記憶體頁面為訪客所有,且無法用於主機程序。

因此,訪客最後可能會產生許多分配的實體記憶體頁面,而這些頁面沒有在使用時,主機的記憶體執行空間可能很低,用於執行自己的程序。

以下介紹 2 種讓主機可使用訪客記憶體的 2 種方式:

超棒的氣球

主機可以設定目標氣球大小,讓訪客 virtio-balloon 驅動程式庫 inflate 為特定大小的氣球。加載說明框意味著訪客會保留所需的記憶體頁面,並將分配的記憶體頁面的訪客實體位址回報給主機。從這個時間點,主機可以解開回報的記憶體頁面,並使用實體記憶體釋出已回報的記憶體。

如果 VIRTIO_BALLOON_F_DEFLATE_ON_OOM 協商,訪客就能隨時開始使用記憶體。請參閱 Virtio 規格 5.5.6.1。目前我們啟用 VIRTIO_BALLOON_F_DEFLATE_ON_OOM。

主機可以透過降低說明框的目標大小,允許訪客重複使用說明框中的頁面。如果設定的氣球大小低於說明框中的實際頁數,訪客可能會重複使用先前提供給該球的頁面。如果訪客想再次使用記憶體,系統會在說明框上 deflate 時,讓主機知道訪客日後將使用特定範圍的實體訪客位址。定義從說明框中移除訪客存取頁面之後,系統會觸發訪客實體來代管實體頁面錯誤,管理程序會為訪客分配新的實體記憶體頁面供訪客使用。

如需 Virtio 氣球核心功能的詳細說明,請參閱 Virtio Balloon. 投影片Virtio Balloon. 影片

免費網頁報表

「virtio-ballon」在 2020 年推出了「免費網頁報表」這項新功能。

免費頁面報表新增一種方式,可讓訪客將免費記憶體頁面回報給主機。訪客方法是在免費網頁報告中加入 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 的免費頁面報表功能收回主機用量的免費記憶體。
  • 在「LOW」和「CRITICAL」主機記憶體壓力事件上加載球體,以清除訪客頁面快取並取回零散的記憶體頁面。
  • 概念證明確認免費網頁報表確實如預期收回記憶體。

實作

使用免費網頁報表

我們會使用免費網頁回報功能功能,向主機回報並收回「所有」免費記憶體。

所有皆為 PAGE_REPORTING_MIN_ORDER 以上的任何順序 (在 Linux kernel 至 4MiB 中定義)。

在接下來的 30 秒內,使用免費網頁報表會收回「大部分」的記憶體。回報的免費頁面大小為 2MiB 或 4MiB,因此預期會出現一些記憶體分割。在訪客端的免費頁面報表中,系統會隨時間調整,盡可能降低效能受到的影響。

Linux-5.15 會以 2MiB 和 4MiB 區塊回報大部分可用記憶體,時間超過 30 秒。

免費頁面報表不會撤銷 Linux 頁面快取,如果訪客執行大量 IO 工作負載,就可能發生問題。如要瞭解 Linux 中的頁面快取,請參閱 Linux 頁面快取基本資訊

日後當 Linux 訪客映像檔開始使用 MGLRU 時,這可能會改變。請參閱 MGLRU 上的「Drawbacks、Alternatives and unknown」部分。

任意將網頁快取移至垃圾桶是好事,存在原因。只有在主機實際需要時,主機才應從訪客頁面快取中擷取記憶體。這表示在主機處於記憶體壓力的情況下,我們需要提供一種方法,可收回用於頁面快取的訪客記憶體。

在主機記憶體壓力時加載客用氣球

第二項變更是使用記憶體壓力提供者,加載警告和 CRITICAL 主機記憶體等級的說明框。

讓氣球升空可以達成以下兩個目標:

  • 如果訪客執行大量檔案 IO 及填充頁面快取,請移除訪客頁面快取。
  • 收回大部分的片段記憶體頁面,因為氣球加載作業是以 4KiB 為精細,而免費網頁報表使用的是 4MiB。

加載量與可用的訪客記憶體成正比。出現「WARNING」和「嚴重」主機記憶體事件時,氣球將加載至 90% 的可用訪客記憶體。我們必須加載 WARNING 和 CRITICAL 事件,以免記憶體從 NORMAL 下降至嚴重的情況。當主機記憶體壓力回到 NORMAL 時,氣球將降至 0%。

我們希望避免在主機低於記憶體壓力時,持續加載和逃出氣球。氣球加載作業對於訪客與主機都會產生效能成本。除此之外,Intel 認為常數氣球調整大小會導致許多 TLB 相關問題

為避免氣球大小來回移動,我們會將氣球加載作業限制為每 X 秒 1 次加載。在 Teamfood 測試期間設定的 X。初始值為 1 分鐘。且可能會產生更多逾時情形,例如當主機長時間保持在記憶體壓力警告中,就會逾時來推遲氣球。可根據 Teamfood 測試遙測資料新增其他逾時時間。

效能

實作記憶體回收功能,可改善使用者在訪客中執行記憶體不足的應用程式時,主機記憶體的效能。主機能夠取得更多記憶體可供使用,而不是採用記憶體壓縮和其他 CPU 高價方法,在訪客具有可回收的記憶體時取得記憶體。

在 Linux 實作中,免費頁面報表作業會保持 30 秒以上,以降低對訪客效能的影響。我們預期 1%-2% 的效能會對 會耗用大量記憶體的訪客工作負載造成影響。請參閱免費網頁報表基準

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

無論主機是否因記憶體壓力而運作 (無論是否啟用記憶體回收功能),我們都必須測量訪客「TLB 掉落」的中斷次數。

基準:

要擷取的指標

  • 透過基準測試回報用於偵測效能迴歸的一般指標
  • 基準前後主機中的可用記憶體
  • 來賓因 TLB 槍擊而中斷

安全性考量

回收的免費頁面不會做為停用作業的一部分,與氣球加載作業一樣。這麼做可避免訪客資訊外洩到主機和其他訪客。

測試

大部分工作將分別透過單元測試和 2 項整合測試完成。一項整合測試會涵蓋免費頁面回報記憶體回收作業,另一個則涵蓋訪客頁面快取的互動功能和氣球加載作業。

將手動測試「動機」一節所述的使用者歷程。 使用者歷程仰賴訪客啟動,因此不具故意。如果我們執行了自動化的端對端虛擬化測試,則可以進一步應用到這個情境。我們認為,針對這個 RFC 建構自動化端對端虛擬化測試,是不合理的做法。

缺點、替代方案和未知

多代 LRU 架構

多代 LRU 架構 (又稱為 MGLRU) 是 Linux kernel 的記憶體改善功能。在 Linux 中目前收回的頁面對 CPU 使用率而言非常昂貴,而且通常很難判斷要剔除哪些項目。MGLRU 的目標是相較於目前的 Linux kernel 頁面收回程式碼,做出更好的選擇,提升執行效率。Google 工程師提供的冷啟動時間減少最多 16%,同時減少記憶體不足終止的情況,但 Chrome OS 發現記憶體不足終止情況的次數減少了 59%,記憶體不足的分頁捨棄量則減少了 96%,伺服器結果也令人印象深刻。

詳情請參閱 PATCH v14 00/14 多代 LRU 架構

我們目前使用的 Termina 5.15 沒有 MGLRU 修補程式。MGLRU 不適用於上游。Termina 核心開發人員正在等待 MGLRU 獲準加入向後移植 ot Termina 5.15

MGLRU API 可用於驅動免費網頁報表邏輯。建議您使用 MGLRU API,改善 Linux 核心的免費頁面回報效能。如果成功,則可建議合併上游。這將針對 Linux 核心中現有的免費網頁報表解決方案進行最佳化。

MGLRU 沒有依附元件,允許主機收回訪客記憶體。

不斷調整氣球大小的替代品

最初建議的執行記憶體收回方法,因此為記憶 Daemon。

這是 ChromeOS 目前使用的方法。遊戲中有許多缺點

  • 需要選擇輪詢間隔。
  • Intel 回報,即使調整小氣球,也會產生效能負擔。請參閱不斷調整空間大小會導致 TLB 擊敗
  • 要達到這個目標,氣球必須隨時加載約 90% 的訪客記憶體。
  • 訪客應用程式可以快速分配,並在下一個輪詢間隔前 OOM Daemon 終止訪客應用程式

ChromeOS 做法

ChromeOS 目前正著手開發新一代的 RTF 格式說明框。上述概念的目的是在訪客和主機中,使用低記憶體終止器來調整氣球大小,而非終止應用程式。我們還打算使用 MGLRU 來引導氣球大小調整邏輯。

ChromeOS 解決的難題更困難,也有多種問題:

  • ChromeOS 有多名訪客,而主機彼此競爭記憶體
  • ChromeOS 和所有訪客都具備 MGLRU 和低記憶體終止 Daemon 的連接。
  • 選擇正確的氣球大小是難以解決所有工作負載的問題。
    • 我們必須定義一套經驗法則,才能引導氣球加載/定義邏輯
    • 請務必收集裝置機群的資料,以便建構經驗法則並分析效果。
    • 更重要的是,如果您使用 LMKD 觸發氣球加載/延遲,否則 OOM 終止員會終止應用程式,同時讓氣球加載/拉近

Fuchsia 虛擬化沒有可供收集統計資料的大型裝置機群。我們想解決的問題就比較簡單。Fuchsia 沒有可以接上 OOM 的殺手。

Fuchsia 主機允許同時執行多位訪客 (Termina、Debian、 Fuchsia)。目前這並非主要的用途,通常是使用者和測試執行單一訪客執行。開始使用更強大的硬體後,這個狀態可能會改變。如果訪客未使用所有可用記憶體,建議解決方案適用於多位過度訂閱的訪客。例如閒置的 Debian 訪客和有效的 Termina 訪客。

如果我們必須支援多位訪客使用所有可用記憶體,問題空間會更大。決定哪些訪客應用程式或訪客更重要的是產品政策。我們應專注於為產品提供合適的工具,但在平台層級中,我們不想釐清記憶體不足的處理方式。

我們會使用更簡單、可預測的解決方案來解決目前問題,同時新增資料收集以分析 OOM,藉此判斷是否需要增加更複雜的經驗法則。

與 DAX 和 virtio-fs 共用主機和訪客網頁快取

DAX 對應可讓訪客直接從主機快取存取檔案內容,避免訪客和主機之間出現重複。新增 virtio-fs 對 DAX 的支援,啟用頁面快取共用功能,以及在記憶體壓力中新增頁面快取捨棄功能,是 virtio 說明框加載功能的替代解決方案。那麼,精細的網頁快取控管機制比較適合,因為氣球加載而撤銷大量頁面快取。我們可以捨棄舊的頁面快取,同時保留新的快取以減輕記憶體壓力,而不會影響主機/訪客的效能。

先前的圖片和參考資料