Understanding Low Memory Management in Android: Kswapd & LMK

Understanding Low Memory Management in Android: Kswapd & LMK

As a mobile operating system, Android has to deal with limited memory resources. The OS carefully monitors memory usage and takes steps to free up memory when it becomes low.

In this article, we discuss how Android allocates memory and reacts to low-memory situations.

Android platform runs on the premise that free memory is wasted memory.

Considering this rule, the Android OS always tries to allocate all the available memory.

This is a very helpful and awesome technique. The system can keep recently used applications in memory, and the user can quickly switch back to them without any launch delays.

Anyways, the memory is there to be USED by the system, and Android OS uses it efficiently. But, what if the entire memory is in use? How can you open more apps? Don’t worry! Android manages that too!

It uses two important concepts: Kswapd and LMK (Low Memory Killer). But first, let’s understand the basics.

Types of memory:

Android devices contain three different types of memory: RAM, zRAM, and storage.

  1. RAM: Fastest but Limited memory.

  2. zRAM: Partition of RAM used for swap space.

Everything is compressed when placed into zRAM, and then decompressed when copied out of zRAM

3. Storage: Contains all of the persistent data.

Pages:

RAM is broken up into pages. Typically each page is 4KB of memory.

A Page(Part of RAM) can be either considered “used” or “unused”(Free).

Now, that used page can either be used by the process we know(let’s say we know process A is using Page number 154) or by some anonymous process(we don’t know who’s using the page).

  • The Page used by the known Process is called “Cache”.
    - Private cache: Owned by one process.
    - Shared cache: Used by multiple processes. (Example: Google services like location can be used by multiple processes)

  • Now, a Cache can be ”Clean” or “Dirty”.
    - Clean: Unmodified copy of some file that is already present in Storage. (Can be deleted and fetched again from storage)
    - Dirty: Modified copy of the file(Modified data will be lost if deleted)

Now, if those pages are almost all used, then Android has to start dealing with them.

Low memory management:

Android has two main mechanisms to deal with low-memory situations: the kernel swap daemon and low-memory killer.

As you might know, Android runs on Linux Kernal and this Linux kernel maintains low and high free memory thresholds.

Kswapd: kernel swap daemon

kswapd reclaims clean pages by deleting them.

  • It becomes active when the free memory of the device falls below the threshold.

  • It stops when free memory reaches the high threshold.

  • The Clean page is deleted and can be easily copied back to RAM from Storage if any process demands it(known as Demand paging).

Clean page, backed by storage, deleted

  • As this was not enough, kswapd can also move cached private dirty pages and anonymous dirty pages to zRAM, where they are compressed. And if any process demands it, then, we can uncompress and get it back.

Dirty page moved to zRAM and compressed

LMK: Low-memory killer

If kswapdcouldn’t free up enough memory required by the system, the kernel started killing the processes to free up more memory using lmk(low-memory killer).

To decide which process to kill, LMK uses an “out of memory” score called oom_adj_score to prioritize the running processes.

Android processes, with high scores at the top and low scores at the bottom

High Scores at the top and low scores at the bottom.

  • Background apps: The least important background app will be closed first.

  • Previous app: The most-recently-used background app. Has higher priority (a lower score) than other background apps.

  • Home app: Launcher app. Killing this will make the wallpaper disappear.

  • Services: Started by applications and may include syncing or uploading to the cloud.

  • Perceptible apps: Apps that are partially visible or still running background tasks. Eg. Playing music

  • Foreground app: The app currently being used. Killing the foreground app looks like an application crash

  • Persistent (services): Core services for the device, such as telephony, Bluetooth, wifi.

  • System: System processes. As these processes are killed, the phone may appear to reboot.

  • Native: Very low-level processes used by the system (for example, kswapd).

To kill an app, the kernel should be aware of the specific pages that are being used by the process, this is called as memory footprint.

There can be also Shared memory Pages, right? I already explained it above.

When determining how much memory is being used by an app, the system must account for shared pages.

There are three ways to determine:

  1. Resident Set Size (RSS): All pages: Shared + Non-Shared.

  2. Proportional Set Size (PSS): Non-Shared pages + an even distribution of the shared pages (for example, if three processes are sharing 3MB, each process gets 1MB in PSS) (This is what is used).

  3. Unique Set Size (USS): Only non-shared pages.

PSS is what is used by OS. PSS takes a long time to calculate because the system needs to determine which pages are shared and by how many processes.

After this, there will be surely some memory available for your new app to run.

If you learned something new, make sure to follow “Sagar Malhotra” for more such android-related content.