RFC-0091:zx_system_get_event ZX_SYSTEM_EVENT_IMMINENT_OUT_OF_MEMORY | |
---|---|
狀態 | 已接受 |
區域 |
|
說明 | 建議在 `zx_system_get_event()` 系統呼叫中新增事件 `ZX_SYSTEM_EVENT_IMMINENT_OUT_OF_MEMORY`。 |
問題 | |
Gerrit 變更 | |
作者 | |
審查人員 | |
提交日期 (年-月-日) | 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 發生時寫出記憶體報告,是不切實際的做法,因為這會與檔案系統關閉作業競爭。因此,這份 RFC 建議公開新事件 ZX_SYSTEM_EVENT_IMMINENT_OUT_OF_MEMORY
,並盡可能在 OOM 前發出信號,同時嘗試在 OOM 前提供一些空間,以便可靠寫出記憶體報告。ZX_SYSTEM_EVENT_OUT_OF_MEMORY
舉例來說,如果系統空閒記憶體等級降至 50 MB 時,系統會傳送 ZX_SYSTEM_EVENT_OUT_OF_MEMORY
信號,如果空閒記憶體為 60 MB,則會傳送 ZX_SYSTEM_EVENT_IMMINENT_OUT_OF_MEMORY
信號。
我們也希望能長期對 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_NORMAL
、ZX_SYSTEM_EVENT_MEMORY_PRESSURE_WARNING
和 ZX_SYSTEM_EVENT_MEMORY_PRESSURE_CRITICAL
,這些事件也不需要 ZX_RIGHT_MANAGE_PROCESS
權限。換句話說,正常、警告、嚴重和即將發生的 OOM 事件可以使用 RootJobForInspect
通訊協定,而 OOM 事件則需要使用 RootJob
通訊協定。
在核心中實作時,只需對現有的記憶體回收邏輯進行最少的變更。我們只是在傳遞至 pmm_init_reclamation()
的浮水印清單中,新增另一個浮水印。Imminent-OOM 層級與其他記憶體壓力層級唯一的差異,在於它不會在核心中觸發任何記憶體回收作業 (即將 pager 備份的記憶體和可捨棄的記憶體淘汰)。這個層級純粹是用於診斷;在此時觸發記憶體回收作業,會變更事件原本要擷取的記憶體狀態。因此,這項新事件在 fuchsia.memorypressure
通訊協定中不會有對應的信號,而這項信號會用於在使用者空間中推動記憶體回收作業。
實作
zx_system_get_event()
系統呼叫可在單一 CL 中延伸;現有核心事件的等候者不會受到這項變更的任何影響。新事件的等候者日後可在個別 CL 中採用該事件。
成效
新事件不會影響現有事件的等待者效能。新事件的效能特徵也應與現有事件相似,無論是擷取事件句柄,還是等待事件句柄,皆是如此。用於發出事件訊號的核心效能也與現有效能相似:當可用記憶體層級變更時,PMM 系統會找出最接近的記憶體浮水印,以便推測記憶體壓力層級;建議只需新增浮水印,而不需要變更現有邏輯的其他部分。
人體工學
無。
回溯相容性
無。
安全性考量
無。
隱私權注意事項
無。
測試
系統會編寫 Zircon 核心測試,用於擷取並等待 ZX_SYSTEM_EVENT_IMMINENT_OUT_OF_MEMORY
。在採用事件時,系統也會撰寫用來驗證用戶端行為的單元測試。
說明文件
zx_system_get_event()
的系統呼叫說明文件需要更新。我們也會在核心概念說明文件中新增項目,說明各種記憶體壓力等級背後的原因、每個等級的預期回應,以及如何與系統的其他部分連結。
缺點、替代方案和未知事項
缺點:記憶體報告可能不準確
由於事件會在 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
,我們確實會使用這個事件來寫入記憶體報告。不過,由於「Critical memory」浮水印與 OOM 浮水印的距離相當遙遠,因此這些報表可能會遺漏與 OOM 較為接近的重要記憶體狀態變更。
替代方案 2:提供更豐富的 API 以記錄更多診斷事件
我們可以提供替代 API,讓使用者指定要通知的多個自訂診斷記憶體層級,而非公開與 OOM 相關的專屬事件。這樣一來,API 就會更具彈性,日後也更容易擴充。不過,目前沒有具體用途可證明這類 API 的實用性。
其他記憶體壓力等級 (可能有助於擷取診斷資訊) 為「警告」和「嚴重」。對於這些層級,我們可以直接使用信號層級變更的核心事件。我們已為「重要」等級執行這項操作。在這個層面上,OOM 等級特別特殊,因為無法在 OOM 發生的確切時間點擷取診斷資訊。在理想情況下,我們會在 OOM 發生時捕捉狀態。由於這麼做是不可能的,我們需要另一個信號,這個信號必須足夠接近 OOM,才能擷取相關狀態,但又不能太接近,否則我們會遇到類似問題,而無法撰寫報告。
既有技術與參考資料
zx_system_get_event
文件說明瞭核心記憶體事件的運作方式。fuchsia.memorypressure
說明文件說明瞭在核心事件上建立的使用者空間記憶體壓力信號。