記憶體不足終止 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 驅動程式連結至板塊縮減器 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