Low Memory Killer Daemon (lmkd)

The Android low memory killer daemon (lmkd) process monitors the memory state of a running Android system and reacts to high memory pressure by killing the least essential processes to keep system performing at acceptable levels.

About memory pressure

An Android system running multiple processes in parallel may encounter situations when system memory is exhausted and processes that require more memory experience noticeable delays. Memory pressure, a state in which the system is running short on memory, requires Android to free memory (to alleviate the pressure) by throttling or killing unimportant processes, requesting processes to free non-critical cached resources, and so on.

Historically, Android monitored system memory pressure using an in-kernel lowmemorykiller driver, a rigid mechanism that depends on hard-coded values. As of kernel 4.12, the lowmemorykiller driver has been removed from the upstream kernel and a userspace lmkd performs memory monitoring and process killing tasks.

Userspace lmkd

The userspace lmkd implements the same functionality as the in-kernel driver but uses existing kernel mechanisms to detect and estimate memory pressure. Such mechanisms include using kernel-generated vmpressure events or pressure stall information (PSI) monitors to get notifications about memory pressure levels, and using memory cgroup features to limit the memory resources allocated to each process based on process importance.

Kill strategies

Userspace lmkd supports kill strategies based on vmpressure events or PSI monitors, their severity, and other hints such as swap utilization. Kill strategies differ between low-memory and high-performance devices:

  • On low-memory devices, the system should tolerate higher memory pressure as a normal mode of operation.
  • On high-performance devices, memory pressure should be viewed as an abnormal situation and fixed before it affects overall performance.

You can configure the kill strategy using the ro.config.low_ram property (for details, see Low RAM Configuration).

Userspace lmkd also supports a legacy mode in which it makes kill decisions using the same strategies as the in-kernel lowmemorykiller driver (that is, free memory and file cache thresholds). To enable legacy mode, set the ro.lmk.use_minfree_levels property to true.

Using userspace lmkd

In Android 9 and higher, userspace lmkd activates if an in-kernel lowmemorykiller driver is not detected. Because userspace lmkd requires kernel support for memory cgroups, the kernel must be compiled with the following configuration settings:

CONFIG_ANDROID_LOW_MEMORY_KILLER=n
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y

Pressure stall information (PSI)

Android 10 and higher support a new lmkd mode that uses kernel pressure stall information (PSI) monitors for memory pressure detection. The PSI patchset in the upstream kernel (backported to 4.9 and 4.14 kernels) measures the amount of time tasks are delayed as a result of memory shortages. As these delays directly affect user experience, they represent a convenient metric for determining memory pressure severity. The upstream kernel also includes PSI monitors that allow privileged userspace processes (such as lmkd) to specify thresholds for these delays and to subscribe to events from the kernel when a threshold is breached.

PSI monitors versus vmpressure signals

Because the vmpressure signals (generated by the kernel for memory pressure detection and used by lmkd) often include numerous false positives, lmkd must perform filtering to determine if the memory is under real pressure. This results in unnecessary lmkd wakeups and use of additional computational resources. Using PSI monitors results in a more accurate memory pressure detection and minimizes filtering overhead.

Using PSI monitors

To use PSI monitors instead of vmpressure events, configure the ro.lmk.use_psi property. The default is true, making PSI monitors the default mechanism of memory pressure detection for lmkd. Because PSI monitors require kernel support, the kernel must include the PSI backport patches and be compiled with PSI support enabled (CONFIG_PSI=y).

Configuring lmkd

Configure lmkd for a specific device using the following properties.

Property Use Default
ro.config.low_ram Choose between low-memory versus high-performance device. false
ro.lmk.use_psi Use PSI monitors (instead of vmpressure events). true
ro.lmk.use_minfree_levels Use free memory and file cache thresholds for making process kill decisions (that is, match the functionality of the in-kernel lowmemorykiller driver. false
ro.lmk.low The minimum oom_adj score for processes eligible to be killed at low vmpressure level. 1001
(disabled)
ro.lmk.medium The minimum oom_adj score for processes eligible to be killed at medium vmpressure level. 800
(cached or non-essential services)
ro.lmk.critical The minimum oom_adj score for processes eligible to be killed at critical vmpressure level. 0
(any process)
ro.lmk.critical_upgrade Enable upgrade to critical level. false
ro.lmk.upgrade_pressure The maximum mem_pressure at which the level is upgraded because the system is swapping too much. 100
(disabled)
ro.lmk.downgrade_pressure The minimum mem_pressure at which a vmpressure event is ignored because enough free memory is still available. 100
(disabled)
ro.lmk.kill_heaviest_task Kill heaviest eligible task (best decision) versus any eligible task (fast decision). true
ro.lmk.kill_timeout_ms Duration in ms after a kill when no additional kill will be done. 0
(disabled)
ro.lmk.debug Enable lmkd debug logs. false

Example device configuration:

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