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 |