記憶體不足終止工具 Daemon

Android 記憶體不足終止工具 Daemon (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 驅動程式的原因有很多,包括:

  • 低 RAM 裝置必須經過積極調整,即使如此,在具有大型檔案支援的活動頁面快取工作負載上,效能仍不佳。表現不佳導致連敗,而且沒有擊殺數。
  • LMK 核心驅動程式依賴可用記憶體限制,不會根據記憶體壓力進行調整。
  • 由於設計僵化,合作夥伴通常會自訂驅動程式,以便在裝置上運作。
  • LMK 驅動程式已連結至 Slab Shrinker API,但該 API 並非為搜尋目標及終止目標等繁重作業而設計,因此會導致 vmscan 程序變慢。

使用者空間 lmkd

使用者空間 lmkd 實作的功能與核心內驅動程式相同,但會使用現有的核心機制偵測及估算記憶體壓力。這類機制包括使用核心產生的 vmpressure 事件或壓力停滯資訊 (PSI) 監控器,接收記憶體壓力層級的通知,以及使用記憶體 cgroup 功能,根據程序重要性限制分配給每個程序的記憶體資源。

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

在 Android 9 以上版本中,如果系統未偵測到核心內 LMK 驅動程式,就會啟動使用者空間 lmkd。由於使用者空間 lmkd 需要核心支援記憶體 Cgroup,因此核心必須使用下列設定編譯:

CONFIG_ANDROID_LOW_MEMORY_KILLER=n
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y

終止策略

Userspace lmkd 支援以 vmpressure 事件或 PSI 監控器為基礎的終止策略、嚴重程度,以及其他提示 (例如交換空間利用率)。低記憶體和高效能裝置的終止策略有所不同:

  • 在記憶體不足的裝置上,系統應容許較高的記憶體壓力,視為正常運作模式。
  • 在高階裝置上,記憶體壓力應視為異常狀況,且應在影響整體效能前修正。

您可以使用 ro.config.low_ram 屬性設定終止策略。

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

設定 lmkd

使用下列屬性為特定裝置設定 lmkd

屬性 使用 預設
ro.config.low_ram 指定裝置是低 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。這項策略會使用 Android 10 推出的 PSI 機制,偵測記憶體壓力。Android 11 中的 lmkd 會考量記憶體資源用量和資源耗盡,避免記憶體不足和效能降低。這項終止策略會取代先前的策略,且適用於高效能和低 RAM (Android Go) 裝置。

核心需求

如果是 Android 11 裝置,lmkd 需要下列核心功能:

  • 加入 PSI 修補程式並啟用 PSI (Android 通用核心 4.9、4.14 和 4.19 提供回溯移植)。
  • 納入 PIDFD 支援修補程式 (Android 通用核心 4.9、4.14 和 4.19 提供回溯移植)。
  • 如果是低 RAM 裝置,請加入記憶體 Cgroup。

核心必須使用下列設定選項編譯:

CONFIG_PSI=y

在 Android 11 中設定 lmkd

Android 11 的記憶體終止策略支援下列微調旋鈕和預設值。這些功能適用於高效能和低 RAM 裝置。

屬性 使用 預設
高效能 RAM 不足
ro.lmk.psi_partial_stall_ms 部分 PSI 停滯的閾值 (以毫秒為單位),用於觸發記憶體不足通知。如果裝置太晚收到記憶體壓力通知,請調低這個值,以便提早觸發通知。如果記憶體壓力通知不必要地觸發,請增加這個值,讓裝置對雜訊的敏感度降低。 70 200
ro.lmk.psi_complete_stall_ms 以毫秒為單位,完整呈現觸發重大記憶體通知的 PSI 停滯閾值。如果裝置太晚收到記憶體壓力重大通知,請調低這個值,以便提早觸發通知。如果重大記憶體壓力通知不必要地觸發,請增加這個值,讓裝置對雜訊的敏感度降低。 700
ro.lmk.thrashing_limit 工作集重新錯誤的最大量,以檔案支援的頁面快取大小總計的百分比表示。如果工作集重新錯誤高於這個值,表示系統正在猛烈地清除頁面快取。如果記憶體壓力影響裝置效能,請降低值以限制顛簸。如果裝置效能因顛簸而遭到不必要的終止,請增加值以允許更多顛簸。 100 30
ro.lmk.thrashing_limit_decay 以原始閾值的百分比表示的劇烈震盪閾值衰減,用於在系統無法復原時降低閾值,即使在終止後也是如此。如果持續的資源耗盡導致不必要的終止作業,請調低值。如果終止後持續猛烈運作的回應速度太慢,請增加這個值。 10 50
ro.lmk.swap_util_max 已交換記憶體量上限,以可交換記憶體總量的百分比表示。如果交換記憶體超過這個限制,表示系統已交換大部分可交換的記憶體,但仍處於壓力之下。如果無法交換的分配作業產生記憶體壓力,且大部分可交換的記憶體已交換出去,就可能發生這種情況。預設值為 100,這會有效停用這項檢查。如果裝置效能在記憶體壓力期間受到影響,且交換空間使用率偏高,但可用交換空間層級未降至 ro.lmk.swap_free_low_percentage,請調低值來限制交換空間使用率。 100 100

下列舊版微調旋鈕也適用於新的終止策略。

屬性 使用 預設
高效能 RAM 不足
ro.lmk.swap_free_low_percentage 可用交換空間占總交換空間的百分比。`lmkd` 會將這個值做為系統何時會被視為交換空間不足的門檻。如果 `lmkd` 在交換空間過多時終止程序,請降低百分比。如果 `lmkd` 終止作業發生得太晚,導致 OOM 終止作業發生,請提高百分比。 20 10
ro.lmk.debug 這會啟用 `lmkd` 偵錯記錄。在調整時啟用偵錯功能。 false