| 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程序已等待「Normal」、「Warning」和「Critical」事件,並在必要時產生記憶體報告,因此可輕鬆擴充,等待「Imminent-OOM」事件。如果報表產生作業是由 OOM 上的有序關機處理,這個事件日後可能會移除,但如果報表提供額外價值,我們也可能決定保留。
設計
核心記憶體回收系統會根據三種記憶體水位線 (警告、嚴重和 OOM) 發出記憶體壓力事件信號。這項邏輯可輕鬆擴充,在「嚴重」和「記憶體不足」之間加入新的「即將發生 OOM」浮水印。您可以透過核心指令列選項,設定即將發生 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 權限。換句話說,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() 的系統呼叫說明文件需要更新。
此外,核心概念說明文件也會新增項目,說明各種記憶體壓力層級背後的動機、每個層級預期的回應,以及這些層級與系統其他部分的關聯。
缺點、替代方案和未知事項
缺點:記憶體報表可能不準確
由於系統會在 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 之前發出信號的其他現有事件是 ZX_SYSTEM_EVENT_MEMORY_PRESSURE_CRITICAL,我們會使用這個事件撰寫記憶體報告。不過,重大記憶體浮水印與 OOM 浮水印的距離很遠,因此這些報表可能會錯過更接近 OOM 的重要記憶體狀態變化。
替代方案 2:更豐富的 API,可提供更多診斷事件
我們可提供替代 API,讓使用者指定多個自訂診斷記憶體層級,以便在這些層級收到通知,而不是在接近 OOM 時公開專門的事件。這樣一來,API 就會更具彈性,日後也更容易擴充。不過,目前沒有具體的使用案例顯示這類 API 的實用性。
其他可能需要擷取診斷資訊的記憶體壓力層級為「警告」和「嚴重」。對於這些層級,我們可以直接使用核心事件,指出層級變更。我們已針對「重大」層級執行這項操作。OOM 層級在這方面比較特殊,因為無法在 OOM 發生時準確擷取診斷資訊。在理想情況下,我們希望在 OOM 發生時擷取狀態。由於這並不可行,我們需要另一個信號,這個信號要夠接近 OOM,才能擷取相關狀態,但又不能太接近,以免遇到類似問題而無法撰寫報表。
既有技術和參考資料
zx_system_get_event
文件說明核心記憶體事件的運作方式。fuchsia.memorypressure
文件說明以核心事件為基礎建構的使用者空間記憶體壓力信號。