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 驅動程式連結至板塊縮減器 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
終止策略
使用者空間 lmkd
支援根據 vmpressure
事件或 PSI 監控器、嚴重程度,以及其他提示 (例如交換使用率) 的終止策略。低記憶體和高效能裝置的終止策略不同:
- 在記憶體較低的裝置上,系統應以正常運作模式容許較高的記憶體壓力。
- 在高效能裝置上,記憶體壓力應視為異常情況,並在影響整體效能前加以修正。
您可以使用 ro.config.low_ram
屬性設定終止策略。詳情請參閱「低 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 裝置,請加入記憶體 Cgroups。
核心必須採用下列設定進行編譯:
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` 會使用這個值做為閾值,用來判斷系統是否處於 Swap 空間不足的狀態。如果 `lmkd` 在 Swap 空間過多時執行終止作業,請降低百分比。如果 `lmkd` 的終止作業發生得太晚,導致 OOM 終止作業,請提高百分比。 | 20 |
10 |
ro.lmk.debug |
這會啟用 `lmkd` 偵錯記錄。在調整時啟用偵錯功能。 | false |