RFC-0091 - zx_system_get_event ZX_SYSTEM_EVENT_IMMINENT_OUT_OF_MEMORY

RFC-0091:zx_system_get_event ZX_SYSTEM_EVENT_IMMINENT_OUT_OF_MEMORY
狀態已接受
區域
  • 核心
說明

提議將「ZX_SYSTEM_EVENT_IMMINENT_OUT_OF_MEMORY」的新事件新增至「zx_system_get_event()」的系統呼叫。

問題
變更
  • 514760
作者
審查人員
提交日期 (年/月)2021-04-12
審查日期 (年/月)2021-05-04

摘要

這個 RFC 建議在 zx_system_get_event() 系統呼叫中加入新的事件類型 ZX_SYSTEM_EVENT_IMMINENT_OUT_OF_MEMORY。系統會在 ZX_SYSTEM_EVENT_OUT_OF_MEMORY 之前發出新的核心事件信號,以便擷取接近 OOM 點的記憶體診斷資訊。

提振精神

當可用實體記憶體即將用盡,以便完成記憶體配置要求時,系統會傳送 ZX_SYSTEM_EVENT_OUT_OF_MEMORY 信號。driver_manager 程序會等待這個 OOM 事件,而當它收到訊號時,會要求 fshost 關閉檔案系統,這樣裝置才能盡可能乾淨地重新啟動。但目前還沒有一個好機制可擷取有意義的記憶體狀態,這對根本造成 OOM 來說至關重要。

只是等待 OOM 事件,並嘗試在 OOM 的時間點編寫記憶體報告是可行的做法,因為這會導致檔案系統停止運作。因此,比起依賴 ZX_SYSTEM_EVENT_OUT_OF_MEMORY,這項 RFC 提議公開新的事件 ZX_SYSTEM_EVENT_IMMINENT_OUT_OF_MEMORY,並盡可能發出接近 OOM 的信號,同時嘗試在 OOM 之前提供緩衝空間,讓記憶體報告確實寫入。舉例來說,如果系統可在系統可用記憶體層級降至 50 MB 時傳送 ZX_SYSTEM_EVENT_OUT_OF_MEMORY 信號,則 ZX_SYSTEM_EVENT_IMMINENT_OUT_OF_MEMORY 就可以以 60 MB 可用記憶體發出訊號。

此外,也有意願長期對 OOM 執行排序關閉,這可能會涉及較高層級的使用者空間元件 (而非 driver_manager),正在等待 ZX_SYSTEM_EVENT_OUT_OF_MEMORY 事件,並關閉特定關鍵元件和檔案系統。這是較大的範圍專案,屆時我們必須重新查看 OOM 事件信號和報告程式碼路徑。因此這個 RFC 中的提案可視為中間步驟,對現有設計有極大的調整。memory_monitor 程序已經等待一般、警告和重大事件,並在必要時產生記憶體報告,因此可輕鬆延長,以等待即將發生的 OOM 事件。如果是由 OOM 優先關閉報表產生程序,我們日後可能會移除這個事件;或者,如果報表提供額外值,我們可能會決定繼續使用此事件。

設計

核心記憶體回收系統會根據三個記憶體浮水印 (警告、嚴重和 OOM) 發出記憶體壓力事件。這個邏輯很容易擴充,以在 Critical 和 OOM 之間加入新的 Imminent-OOM 浮水印。Imminent-OOM 和 OOM 浮水印之間的差異可透過核心指令列選項設定。

為了與現有記憶體浮水印的一致性 (也可以透過核心指令列設定),這個差異值會是記憶體的絕對量 (以 MB 為單位)。這也意味著,單一值可能不適用於部分平台,且需要調整,這是現有記憶體浮水印共用的屬性。此外,記憶體報表產生本身需要特定數量的記憶體,在選擇此差異的值時也應考慮到這一點。

和其他 zx_system_get_event() 支援的核心事件相同,系統會需要根工作的處理常式。與 ZX_SYSTEM_EVENT_OUT_OF_MEMORY 不同,ZX_SYSTEM_EVENT_IMMINENT_OUT_OF_MEMORY 不需要 ZX_RIGHT_MANAGE_PROCESS 右方。這會讓新事件類似於 ZX_SYSTEM_EVENT_MEMORY_PRESSURE_NORMALZX_SYSTEM_EVENT_MEMORY_PRESSURE_WARNINGZX_SYSTEM_EVENT_MEMORY_PRESSURE_CRITICAL,也不需要正確 ZX_RIGHT_MANAGE_PROCESS。也就是說,「Normal」、「Warning」、「Critical」和「Imminent-OOM」事件可以使用 RootJobForInspect 通訊協定,而 OOM 事件則需要使用 RootJob 通訊協定。

如要在核心中實作,請盡量減少現有的記憶體回收邏輯。我們只是在傳遞至 pmm_init_reclamation() 的浮水印清單中新增另一個浮水印。Imminent-OOM 等級與其他記憶體壓力等級不同的地方,在於其不會在核心中觸發任何記憶體收回 (剔除分頁器支援記憶體和可捨棄的記憶體)。這個層級僅做為診斷層級,此時觸發記憶體重新復原會改變事件原本要擷取的記憶體狀態。因此,這個新事件在 fuchsia.memorypressure 通訊協定中不會有對應信號,該信號用於在使用者空間中回收記憶體。

實作

zx_system_get_event() 系統呼叫可以在單一 CL 中擴充,現有核心事件的等候程序不會受到這項異動的影響。新事件的等待人員可以稍後在另一個 CL 中採用新事件。

效能

新事件不會影響現有事件等候程序的效能。新事件也預期具有與現有事件類似的效能特性,兩者皆用於擷取事件控點及等待該事件。傳送事件信號的核心效能也與現有類似,當免費記憶體等級變更時,PMM 系統會尋找最接近的記憶體浮水印,藉此推斷記憶體壓力等級;本提案只是新增浮水印,而無需變更現有邏輯的其餘部分。

人體工學

無。

回溯相容性

無。

安全性考量

無。

隱私權注意事項

無。

測試

系統會編寫 Zircon 核心測試,並在 ZX_SYSTEM_EVENT_IMMINENT_OUT_OF_MEMORY 擷取並等待。此外,採用事件時,也會編寫用於驗證用戶端行為的單元測試。

說明文件

zx_system_get_event() 的 Syscall 說明文件需要更新。核心概念說明文件也會新增一個項目,說明不同記憶體壓力等級背後的動機、每個預期回應的動機,以及這些項目如何與系統的其餘部分關聯。

缺點、替代方案和未知

缺點:記憶體報表可能不精確

由於事件在 OOM 之前會收到信號,因此擷取的記憶體狀態不會與 OOM 完全一致。不過,只要 OOM 浮水印中的差異值夠小 (幾十 MB),應該仍能對 OOM 進行診斷。

我們可能會發現在產生報表時沒有加入 OOM 的情況,亦即裝置在即將發生 OOM 事件後可以復原。雖然這類報告不會有相關的 OOM 事件,但由於這類報表仍代表記憶體用量增加,因此值得調查。

如果記憶體配置快速增加,事件的等候程序也可能無法產生報表。這類情況還是必須在本機重現問題,同時平行收集記憶體指標來診斷這類情況。報表應該還是能擷取大部分的 OOM 記憶體診斷資料,因為分配的快速增加量很少見。

替代方法 1:使用現有事件而非新事件

ZX_SYSTEM_EVENT_OUT_OF_MEMORY 無法可靠地編寫記憶體報表。這是因為 OOM 事件用於驅動檔案系統關閉,因此可能無法及時編寫報表。

如要改變這種互動方式,請將 OOM 信號處理方式從 driver_manager 移至另一個使用者空間元件,進而導致更嚴重的關閉程序:首先請編寫報表,然後關閉檔案系統。這個方法需要執行一些同步處理作業,確保在檔案系統關閉前,報表已順利撰寫。這可能也需要在傳送 OOM 信號後放寬 OOM 浮水印和重新啟動延遲間隔,因為我們現在會在收到 OOM 事件時執行更多工作。變更 OOM 信號的處理方式,隨著 OOM 嚴格關閉程序 (簡述如「動機」一節所述) 而有更大範圍的調整,日後可能會涉及較大的範圍。

在 OOM 之前發出信號的另一個現有事件是 ZX_SYSTEM_EVENT_MEMORY_PRESSURE_CRITICAL,我們會使用這個值來寫入記憶體報表。不過,「關鍵」記憶體浮水印遠勝 OOM 浮水印,因此這類報表可能會錯過接近 OOM 的重要記憶體狀態變更。

替代方法 2:提供更多診斷事件的豐富 API

除了在 OOM 附近公開特殊事件,我們還可以提供替代 API,讓使用者指定多個自訂診斷記憶體等級做為通知。這可讓您使用更靈活的 API,在日後擴充。不過,目前沒有任何具體用途,指出這類 API 會很實用。

其他可能有助於擷取診斷資訊的記憶體壓力等級,稱為「Warning」和「Critical」。對於這些層級,我們可以直接使用核心事件,指出等級變更。我們在「重要」層級執行了這項動作OOM 層級在這點方面顯而易見,因為無法在 OOM 的時間點擷取診斷結果。我們想要在理想情況下 擷取 OOM 點的狀態。由於這種情況並不可行,我們需要靠近 OOM 的另一個信號才能擷取相關狀態,但為了擷取相關狀態而十分接近,也無法撰寫報告。

先前的圖片和參考資料

zx_system_get_event 說明文件會說明核心記憶體事件的運作方式。fuchsia.memorypressure 說明文件說明在核心事件之上建構的使用者空間記憶體壓力信號。