Android低記憶體終止守護程式

yooooooo發表於2024-12-02

Android 低記憶體終止守護程式 (lmkd) 程序可監控執行中的 Android 系統的記憶體狀態,並透過終止最不必要的程序來應對記憶體壓力大的問題,使系統以可接受的效能水平執行。

記憶體壓力簡介

並行執行多個程序的 Android 系統可能會遇到系統記憶體耗盡,需要更多記憶體的程序出現明顯延遲的情況。記憶體壓力是系統記憶體不足的一種狀態,它需要 Android 透過限制或終止不必要的程序、請求程序釋放非關鍵快取資源等方式來釋放記憶體(以緩解這種壓力)。

過去,Android 使用核心中的低記憶體終止守護程式 (LMK) 驅動程式來監控系統記憶體壓力,該驅動程式是一種依賴於硬編碼值的嚴格機制。從核心 4.12 開始,LMK 驅動程式已從上游核心中移除,改由使用者空間 lmkd 來執行記憶體監控和程序終止任務。

壓力失速資訊

Android 10 及更高版本支援新的 lmkd 模式,它使用核心壓力失速資訊 (PSI) 監視器來檢測記憶體壓力。上游核心中的 PSI 補丁程式集(已向後移植到 4.9 和 4.14 核心)可測量由於記憶體不足導致任務延遲的時間。由於這些延遲會直接影響使用者體驗,因此它們代表了確定記憶體壓力嚴重性的便捷指標。上游核心還包括 PSI 監視器,這類監視器允許特權使用者空間程序(例如 lmkd)指定這些延遲的閾值,並在突破閾值時從核心訂閱事件。

PSI 監視器與 vmpressure 訊號

由於 vmpressure 訊號(由核心生成,用於檢測記憶體壓力並由 lmkd 使用)通常包含大量誤報,因此 lmkd 必須執行過濾以確定是否真的存在記憶體壓力。這會導致不必要的 lmkd 喚醒並使用額外的計算資源。使用 PSI 監視器可以實現更精確的記憶體壓力檢測,並最大限度地減少過濾開銷。

使用 PSI 監視器

如需使用 PSI 監視器(而不是 vmpressure 事件),請配置 ro.lmk.use_psi 屬性。預設值為 true,這會以 PSI 監視器作為 lmkd 記憶體壓力檢測的預設機制。由於 PSI 監視器需要核心支援,因此核心必須包含 PSI 向後移植補丁,並在啟用 PSI 支援 (CONFIG_PSI=y) 的情況下進行編譯。

核心中 LMK 驅動程式的缺點

由於存在大量問題,Android 棄用了 LMK 驅動程式,問題包括:

  • 對於低記憶體裝置,必須主動進行調整,即便如此,在處理涉及支援大檔案的活躍頁面快取的工作負載時,其效能也較差。效能不良會導致出現抖動,但不會終止。
  • LMK 核心驅動程式依賴於可用記憶體限制,不會根據記憶體壓力進行擴縮。
  • 由於設計的嚴格性,合作伙伴通常會自定義該驅動程式,使其可以在自己的裝置上使用。
  • LMK 驅動程式已掛接到 Slab Shrinker API,該 API 並非為了執行繁重操作(例如搜尋並終止目標)而設計,這類操作會導致 vmscan 程序變慢。

使用者空間 lmkd

使用者空間 lmkd 可實現與核心中的驅動程式相同的功能,但它使用現有的核心機制檢測和評估記憶體壓力。這些機制包括使用核心生成的 vmpressure 事件或壓力失速資訊 (PSI) 監視器來獲取關於記憶體壓力水平的通知,以及使用記憶體 cgroup 功能限制根據程序的重要性分配給每個程序的記憶體資源。

在 Android 10 中使用使用者空間 lmkd

在 Android 9 及更高版本中,使用者空間 lmkd 會在未檢測到核心中的 LMK 驅動程式時啟用。由於使用者空間 lmkd 要求核心支援記憶體 cgroup,因此必須使用以下配置設定編譯核心:

CONFIG_ANDROID_LOW_MEMORY_KILLER=n
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y

終止策略

使用者空間 lmkd 支援基於以下各項的終止策略:vmpressure 事件或 PSI 監視器、其嚴重性以及交換利用率等其他提示。低記憶體裝置和高效能裝置的終止策略有所不同:

  • 對於記憶體不足的裝置,一般情況下,系統會選擇承受較大的記憶體壓力。
  • 對於高效能裝置,如果出現記憶體壓力,則會視為異常情況,應及時修復,以免影響整體效能。

您可以使用 ro.config.low_ram 屬性配置終止策略。如需瞭解詳情,請參閱低 RAM 配置

使用者空間 lmkd 還支援一種舊模式,在該模式下,它使用與核心中的 LMK 驅動程式相同的策略(即可用記憶體和檔案快取閾值)做出終止決策。要啟用舊模式,請將 ro.lmk.use_minfree_levels 屬性設定為 true

配置 lmkd

使用以下屬性為特定裝置配置 lmkd

屬性 使用 預設值
ro.config.low_ram 指定裝置是低記憶體裝置還是高效能裝置。 false
ro.lmk.use_psi 使用 PSI 監視器(而不是 vmpressure 事件)。 true
ro.lmk.use_minfree_levels 使用可用記憶體和檔案快取閾值來做出程序終止決策(即與核心中的 LMK 驅動程式的功能一致)。 false
ro.lmk.low 在低 vmpressure 水平下可被終止的程序的最低 oom_adj 得分。 1001 (停用)
ro.lmk.medium 在中等 vmpressure 水平下可被終止的程序的最低 oom_adj 得分。 800 (已快取或非必要服務)
ro.lmk.critical 在臨界 vmpressure 水平下可被終止的程序的最低 oom_adj 得分。 0 (任何程序)
ro.lmk.critical_upgrade 支援升級到臨界水平。 false
ro.lmk.upgrade_pressure 由於系統交換次數過多,將在該水平執行水平升級的 mem_pressure 上限。 100 (停用)
ro.lmk.downgrade_pressure 由於仍有足夠的可用記憶體,將在該水平忽略 vmpressure 事件的 mem_pressure 下限。 100 (停用)
ro.lmk.kill_heaviest_task 終止符合條件的最繁重任務(最佳決策)與終止符合條件的任何任務(快速決策)。 false
ro.lmk.kill_timeout_ms 從某次終止後到其他終止完成之前的持續時間(以毫秒為單位)。 0 (停用)
ro.lmk.debug 啟用 lmkd 除錯日誌。 false

裝置配置示例:

PRODUCT_PROPERTY_OVERRIDES += \
    ro.lmk.low=1001 \
    ro.lmk.medium=800 \
    ro.lmk.critical=0 \
    ro.lmk.critical_upgrade=false \
    ro.lmk.upgrade_pressure=100 \
    ro.lmk.downgrade_pressure=100 \
    ro.lmk.kill_heaviest_task=true

Android 11 中的使用者空間 lmkd

Android 11 透過引入新的終止策略改進了 lmkd。該終止策略使用 PSI 機制來執行 Android 10 中引入的記憶體壓力檢測。Android 11 中的 lmkd 會根據記憶體資源使用情況和抖動來防止出現記憶體不足和效能下降。這一終止策略取代了以前的策略,可同時用於高效能裝置和低記憶體 (Android Go) 裝置。

核心要求

對於 Android 11 裝置,lmkd 需要以下核心功能:

  • 新增 PSI 補丁並啟用 PSI(Android 通用核心 4.9、4.14 和 4.19 中提供向後移植)。
  • 新增 PIDFD 支援補丁(Android 通用核心 4.9、4.14 和 4.19 中提供向後移植)。
  • 對於低記憶體裝置,新增記憶體 cgroup。

必須使用以下配置設定編譯核心:

CONFIG_PSI=y

在 Android 11 中配置 lmkd

Android 11 中的記憶體終止策略支援下面列出的調節旋鈕和預設值。這些功能在高效能裝置和低記憶體裝置上都可使用。

屬性 使用 預設值 預設值
高效能 低記憶體 高效能 低記憶體
ro.lmk.psi_partial_stall_ms 部分 PSI 失速閾值(以毫秒為單位),用於觸發記憶體不足通知。如果裝置收到記憶體壓力通知的時間太晚,可以降低此值以在較早的時間觸發通知。如果在不必要的情況下觸發了記憶體壓力通知,請提高此值以降低裝置對噪聲的敏感度。 70 200
ro.lmk.psi_complete_stall_ms 完全 PSI 失速閾值(以毫秒為單位),用於觸發關鍵記憶體通知。如果裝置收到關鍵記憶體壓力通知的時間太晚,可以降低該值以在較早的時間觸發通知。如果在不必要的情況下觸發了關鍵記憶體壓力通知,可以提高該值以降低裝置對噪聲的敏感度。 700
ro.lmk.thrashing_limit 工作集 refault 數量的上限,以佔具有檔案支援的頁面快取總大小的百分比表示。如果工作集 refault 的數量超過該值,則視為系統對其頁面快取造成抖動。如果裝置效能在記憶體壓力期間受到影響,請降低該值以限制抖動。如果因抖動原因而導致裝置效能不必要地降低,請提高該值以允許更多抖動。 100 30
ro.lmk.thrashing_limit_decay 抖動閾值衰減,以佔在系統無法恢復時(甚至是終止後)用於降低閾值的原始閾值的百分比表示。如果持續抖動導致不必要的終止,請降低該值。如果終止後對持續抖動的響應速度過慢,請提高該值。 10 50
ro.lmk.swap_util_max 最大交換記憶體量,以佔可交換記憶體總量的百分比表示。如果交換的記憶體量超過此上限,則表示系統在交換了其大部分可交換記憶體後仍然存在壓力。 當記憶體壓力是由不可交換記憶體的分配導致時,就可能會發生這種情況,原因在於大部分可交換記憶體已經交換,所以無法透過交換來緩解這一壓力。預設值為 100,這實際上會停用此檢查。如果裝置的效能在交換利用率較高且可用交換水平未降至 ro.lmk.swap_free_low_percentage 的記憶體壓力期間受到影響,請降低該值以限制交換利用率。 100 100

以下舊的調節旋鈕也可用於新的終止策略。

屬性 使用 預設值 預設值
高效能 低記憶體 高效能 低記憶體
ro.lmk.swap_free_low_percentage 可用交換水平,以佔總交換空間的百分比表示。“lmkd”使用該值作為閾值來判斷何時將系統視為交換空間不足。如果“lmkd”因交換空間過多而終止,請降低該百分比。如果“lmkd”終止得太晚,從而導致 OOM 終止,請提高該百分比。 20 10
ro.lmk.debug 這會啟用“lmkd”除錯日誌。在調節時啟用除錯。 false

相關文章