What's this thread about?
This is a brief account of some useful aspects of android memory management and what could be done to make it better or to suit our needs. This is arranged in two parts; A) RAM Management Lesson. B) RAM Management Tips. Whoever is familiar with the Android RAM management concepts can skip to the second part (2nd post). Please read and understand carefully before applying anything to the phone. I'm not responsible for any unwanted effects thereby. Credits belong to respective authors of any MOD/APP discussed here.
A) RAM Management Lesson
Android uses a different way of handling processes. Instead of killing every process after its activity ended, processes are kept until the system needs more memory. The idea is to give speed improvements if you start that activity again. But how/when does Android kill a process if it needs more memory and and which process to kill first?
This is managed by the LMK (Low Memory Killer) driver of Android. You may already know that every app/process in Android is assigned an oom_adj value, which indicates the likelihood of it being killed when an out of memory (OOM) situation occurs. More higher it's value, the higher likelihood of it getting killed. Valid range is -17 to +15. (if in the -17 range means it won't get killed). According to that, there are six groups (OOM groups), into which apps/processes are categorised:
1. Foreground app
2. Visible app
3. Secondary server
4. Hidden app
5. Content provider
6. Empty app
Basically these could be described as..
// This is the process running the current foreground app. We'd really
// rather not kill it!
// This is a process only hosting activities that are visible to the
// user, so we'd prefer they don't disappear.
// This is a process holding a secondary server -- killing it will not
// have much of an impact as far as the user is concerned.
// This is a process only hosting activities that are not visible,
// so it can be killed without any disruption.
// This is a process with a content provider that does not have any clients
// attached to it. If it did have any clients, its adjustment would be the
// one for the highest-priority of those processes.
// This is a process without anything currently running in it. Definitely
// the first to go!
Why their "killability" differ? Apps belonging to these different groups (that have different oom_adj's), start to get killed at different levels of free RAM. These triggering RAM limits are defined by the LMK minfree values. Above 6 categories correspond with 6 RAM limits which are set in the LMK minfree. Eg: Stock Android 4.3 in our SP comes with the minfree values of 58,68,78,88,98,118. (these are in MB; see below how to check it). Practically what it means is, Empty apps will get killed when ram goes below 118mb, Content providers when it goes below 98mb, Hidden apps when it goes below 88mb and so on.. lastly starts killing Foreground apps when ram goes below 58mb. You may notice that this last value (58mb) is not desirable when using memory intensive apps like heavy games. The app might shutdown while we interact with it. It won't be a surprise if RealRacing3 would shutdown in the middle of a race with these minfree settings!
1. In our SP (and newer kernels), oom_score_adj is used instead of old oom_adj. (oom_score_adj valid range is -1000 to 1000). But oom_adj is also maintained for compatibility I think.
2. It is said that there are many OOM process categories that are assigned different oom_adj priorities by the ActivityManagerService, but eventually all of those would be considered under above six slots/groups (according to oom_limits), for the purpose of killing by the LMK minfree triggers. Therefore, those six are the importatnt ones for normal users like us.
Now, to the practically important part...
# We can check the minfree values (also change them) and see the OOM groupings of apps/processes with this Memory Manager app easily.
a) LMK Minfrees:................... ......................................b) OOM groupings:
If we click on an app in the list and select 'more info', we can see it's oom_adj value. In my case, System UI has -12 (foreground), Home Launcher has 1 (visible group) etc..
# We can check these manually in a terminal too..
a) LMK Minfrees:
Give the following command (without quotes) in a terminal emulator or adb shell: "cat /sys/module/lowmemorykiller/parameters/minfree"
$ cat /sys/module/lowmemorykiller/parameters/minfree 15000,17532,20065,22598,25131,30263
b) OOM_adj value of an app:
E.g. take home launcher. Find out it's PID (process ID) like this.. (command with output posted)
$ ps |grep home u0_a26 1653 721 471408 78076 ffffffff 00000000 S com.sonyericsson.home
$ cat /proc/1653/oom_adj 1
At the same time we can see the new oom_score_adj..
$ cat /proc/1653/oom_score_adj 58
oom_score_adj = (oom_adj x 1000)/17 (truncate the decimals). So, (1x1000)/17=58.823
*There's another value (0-1000) of oom_score (cat /proc/1653/oom_score), which is THE actual indicator of how likely a process will get killed. It changes according to the tunable oom_score_adj and other factors..? something like that.. forget it!
## The above mechanism could also be described according to what is mentioned in kernel source files, as below. Can skip if it's boring ..
* The lowmemorykiller driver lets user-space specify a set of memory thresholds
* where processes with a range of oom_score_adj values will get killed. Specify
* the minimum oom_score_adj values in
* /sys/module/lowmemorykiller/parameters/adj and the number of free pages in
* /sys/module/lowmemorykiller/parameters/minfree. Both files take a comma
* separated list of numbers in ascending order.
* For example, write "0,8" to /sys/module/lowmemorykiller/parameters/adj and
* "1024,4096" to /sys/module/lowmemorykiller/parameters/minfree to kill
* processes with a oom_score_adj value of 8 or higher when the free memory
* drops below 4096 pages and kill processes with a oom_score_adj value of 0 or
* higher when the free memory drops below 1024 pages.
* The driver considers memory used for caches to be free, but if a large
* percentage of the cached memory is locked this can be very inaccurate
* and processes may not get killed until the normal oom killer is triggered.
Another point to note is what mentioned above in the kernel source file "..driver considers memory used for caches to be free..", which is described below.
What is "Free RAM"?
What's reported in many apps as "free ram" is actually not free/empty. Linux/Android always tries to utilise the whole ram in some way, so the ram is not wasted. Ram which is not used by active apps, is used for caching apps and for some buffers. These caches and buffers can release memory for apps when needed. We can see the ram usage in detail with this command.. "cat /proc/meminfo" [giving "watch cat /proc/meminfo" would refresh the output every 2 seconds].
$ cat /proc/meminfo MemTotal: 859764 kB MemFree: 26380 kB Buffers: 2008 kB Cached: 136600 kB SwapCached: 0 kB Active: 557312 kB Inactive: 70520 kB ...blah.. ..blah... ....
-->> RAM Management Tips