An explanation of Android memory management mechanism

Source: Internet
Author: User
Tags home screen

?? A common feature of embedded devices is that memory capacity is relatively limited. When running more than a certain number of programs, or involved in complex calculations, it is likely that there is not enough memory, resulting in a system lag. The Android system is no exception, and it also faces the dilemma of physical memory shortages in the device. For Android programs that have been started once, the time it takes to start again is significantly reduced. The reason is that Android does not immediately clean up programs that have been "out of view" (such as when you call Activity.finish to exit the UI). They still reside in memory for a certain amount of time. The advantage of this is that the next boot does not need to re-create a process for the program; The downside is that it increases the probability of the memory oom.

Linux memory Monitoring Mechanism (Oomkiller)

?? Android is Linux-based, and the Linux underlying kernel has its own memory monitoring mechanism, the oomkiller. Once the system's available memory reaches a critical value, the Oom Manager automatically jumps out to clean up the memory.

Oomkiller have different strategies and different ways of dealing with them. Its core ideas are as follows:

In order of priority, the process is gradually killed from low to high, and the memory is reclaimed.

Priority setting strategy mainly considers two aspects: one is to consider the degree of damage to the system (such as the core process of the system, the priority is usually higher), on the other hand also want to release as much useless memory as possible. A reasonable strategy should at least consider the following factors:

    • memory consumed by the process
    • CPU time consumed by the process
    • Oom_adj (oom weight)

?? The process managed by the kernel has a value that measures its oom weight, stored in the/proc/< PID >/oom_adj. Based on this weight value and a number of other factors mentioned above, the system scores each process in real time to determine which processes should be killed in Oom.
This value is stored in the/proc/< PID >/oom_score.
The lower the oom_score fraction, the less likely it is to be killed, or the later it is killed.
The following shows the PID of the NetworkManager process of the Oom_adj and Oom_score, you can see low scores, indicating that this process is very important, generally not killed by the system.

Android Memory management mechanism

Based on the core idea of the Linux kernel Oom Killer, the Android system expands its own memory monitoring system. Because the memory killer under Linux needs to wait until the system resources are "on the brink" of the situation will produce effect, and Android has achieved its own killer.

For this reason, the Android system developed a dedicated driver named Low Memory Killer (LMK). the source path is in the drivers/staging/android/lowmemorykiller.c of the kernel project.
Its driver load function is as follows:

staticint __init lowmem_init(void){    register_shrinker(&lowmem_shrinker);    return0;}

Visible LMK Registers a Shrinker listener callback with the kernel thread, implementing the Lowmem_shrinker. This callback is executed when the idle page of the system is below a certain threshold.

Two arrays are defined in LOWMEMORYKILLER.C, respectively:

Static  Shortlowmem_adj[6] = {0,1,6, A, };Static intLowmem_adj_size =4;//The values below are in this unit (page size)Static intlowmem_minfree[6] = {3* +,/ * 6MB * /    2*1024x768,/ * 8MB * /    4*1024x768,/ * 16MB * /     -*1024x768,/ * 64MB * /};

The first array, Lowmem_adj, has a maximum of 6 elements, which defines only 4 by default, which represents the adj value that needs to be processed when the usable capacity is at "one level", and the second array is a description of "hierarchy". This may not be clear, for example, the first element of Lowmem_minfree is 3*512,3*512*LOWMEM_ADJ_SIZE=6MB. means that when the available memory is less than 6MB, killer needs to clean up the value of adj 0 (that is, lowmem_ The first element of the Adj) of those processes below. Where the value range of adj is -17~15, the smaller the number indicates the higher the process level, usually only 0-15 is used.

is the implementation diagram of the LWK mechanism.

These two arrays are just predefined values for the system and can be tailored to the actual needs of the project.

The Android system provides the appropriate files for us to modify these two sets of values.

The path is as follows:

/sys/module/lowmemorykiller/parameters/adj/sys/module/lowmemorykiller/parameters/minfree

The following statements can be added to the init.rc (the first script parsed by the INIT process at system startup). The init.rc path is/system/core/rootdir/init.rc

/sys/module/lowmemorykiller/parameters/adj  0,8/sys/module/lowmemorykiller/parameters/minfree 1024,4096
Android Process Categories

The size of the process Omm_adj is related to the type of process and the order in which the process is dispatched.

In Android, the process is mainly divided into the following categories:

1. Foreground process (foreground)

?? The process that is currently being displayed on the screen and some system processes. For example, a system process such as Dialer,storage,google search is the foreground process, and for example, when you run a program, such as a browser, when the browser interface is displayed in the foreground, the browser belongs to the foreground process (foreground), But once you press home to return to the main screen, the browser becomes a daemon (background). The last process we want to terminate is the foreground process.

2. Visible process (visible)

?? Visible process is some no longer the foreground, but the user is still visible process, for example: Widgets, Input method, etc., belong to the visible. Although this part of the process is not in the foreground, but also closely related to our use, we do not want them to be terminated (you certainly do not want the clock, weather, news and other widgets are terminated, then they will not sync, you do not want the input method is terminated, otherwise you need to restart the input method).

3. Desktop process (Home app)

?? That is, launcher ensures that after a multi-task switchover, you can quickly return to the home screen without reloading the launcher.

4. Secondary services (secondary server)

?? Some of the services currently running (major services, such as dialing, etc., are not likely to be terminated by the process management, so this is only a minor service), for example: Google Enterprise Suite, gmail internal storage, contact internal storage, and so on. Although this part of the service is a secondary service, but some of the system functions are still closely related, we often need to use them, so we do not want them to be terminated.

5. Background process (hidden)

?? That is the background process (background), which is the process that we generally understand to be switched to the background after startup, such as a browser, a reader, and so on. When the program is displayed on the screen, the process that he runs is the foreground process (foreground), and once we press home to return to the main interface (note that by pressing home, not pressing back), the program resides in the background and becomes the background process (background). Background process Management policy has a variety of: in a more positive way, once the program arrives in the background immediately terminate, this way will increase the speed of the program, but can not speed up the program to start again, there are more negative ways, as much as possible to retain the background program, although it may affect the speed of a single program, However, the speed is increased when you start a program that has started again. This will require users to find a balance based on their own usage habits.

6. Content Provisioning Node (contents provider)

There is no program entity, to provide content for other programs to use, such as the Calendar supply node, mail supply node and so on. Such procedures should have a higher priority when the process is terminated.

7. Null process (empty)

?? There is nothing in the process of running, some programs, such as BTE, after the program exits, will still reside in the process of an empty process, the process is not any data running, the role is often to improve the program's next startup speed or record some of the history of the program. this part of the process is undoubtedly the first to be terminated .

In the relevant code file Processlist.java for the process used by AMS, different types of adj values are defined, as follows:

/*** Omit other code * /    //Unknown adj    Static Final intUnknown_adj = -;Static Final intCached_app_max_adj = the;Static Final intCached_app_min_adj =9;//b List of service, less adhesive to user than a list    Static Final intService_b_adj =8;//user previous interaction process    Static Final intPrevious_app_adj =7;//launcher Process    Static Final intHome_app_adj =6;//process running the application service    Static Final intService_adj =5;//Heavyweight application process    Static Final intHeavy_weight_app_adj =4;//For processes that host backup-related operations    Static Final intBackup_app_adj =3;//Such processes can be perceived by the user but not visible, such as the music player running in the background    Static Final intPerceptible_app_adj =2;//There is a visible activity process in the foreground, which can severely affect the user experience if such processes are easily killed    Static Final intVisible_app_adj =1;//The process that is currently running, that is, the program that the user is interacting with    Static Final intForeground_app_adj =0;Static Final intPersistent_service_adj =- One;//persistent nature of the process, such as telephony    Static Final intPersistent_proc_adj =- A;//System process    Static Final intSystem_adj =- -;/*** Omit other code * /

The Adj value defined above shows that the smaller the adj, the more important the process type is, and, in particular, the default Oom_adj of the system process is-16, which is never killed.

Also note is the Updateoomlevels function, the internal principle is achieved by writing the above two files, AMS will automatically correct the system according to the current configuration of Adj and minfree, in order to adapt to the best possible different hardware. The function source code is as follows:

Private void Updateoomlevels(intDisplaywidth,intDisplayheight, Boolean write) {//scale buckets from avail memory:at 300MB We use the lowest values to        //700MB or more for the top values.        floatScalemem = ((float) (mtotalmemmb- -))/( the- -);//Scale buckets from the screen size.        intMinSize =480* -;//384000        intMaxSize = the* -;//1024000 230400 870400.        floatScaledisp = ((float) (displaywidth*displayheight)-minsize)/(maxsize-minsize);if(false) {SLOG.I ("XXXXXX","scalemem="+ Scalemem); SLOG.I ("XXXXXX","scaledisp="+ Scaledisp +"dw="+ Displaywidth +"Dh="+ displayheight); }floatScale = SCALEMEM > Scaledisp? Scalemem:scaledisp;if(Scale <0) scale =0;Else if(Scale >1) scale =1;intMinfree_adj = Resources.getsystem (). Getinteger (com.android.Internal. R.integer.config_lowmemorykillerminfreekbytesadjust);intMinfree_abs = Resources.getsystem (). Getinteger (com.android.Internal. R.integer.config_lowmemorykillerminfreekbytesabsolute);if(false) {SLOG.I ("XXXXXX","minfree_adj="+ Minfree_adj +"minfree_abs="+ Minfree_abs); }//We ' ve now baked in the increase to the basic oom values above, since        //They seem to being useful more generally for devices that is tight on        //memory than just for. This should probably has some more        //tuning done, so not deleting it quite yet ...Final Boolean is64bit =false;//build.supported_64_bit_abis.length > 0;         for(intI=0; i<moomadj.length; i++) {intlow = Moomminfreelow[i];intHigh = Moomminfreehigh[i]; Moomminfree[i] = (int) (Low + ((high-low) *scale));if(Is64bit) {//On-bit devices, we consume more baseline RAM, because-bit is cool!                //To avoid being all pagey and stuff, scale up the memory levels to                //Give us some breathing.Moomminfree[i] = (3*moomminfree[i])/2; }        }if(Minfree_abs >=0) { for(intI=0; i<moomadj.length; i++) {Moomminfree[i] = (int)((float) Minfree_abs * Moomminfree[i]/moomminfree[moomadj.length-1]); }        }if(Minfree_adj! =0) { for(intI=0; i<moomadj.length; i++) {Moomminfree[i] + = (int)((float) Minfree_adj * Moomminfree[i]/moomminfree[moomadj.length-1]);if(Moomminfree[i] <0) {Moomminfree[i] =0; }            }        }//The maximum size we'll restore a process from cached to background, when under        //Memory duress, is 1/3 the size we have reserved for kernel caches and other overhead        //before killing background processes.Mcachedrestorelevel = (Getmemlevel (PROCESSLIST.CACHED_APP_MAX_ADJ)/1024x768) /3;//Ask the kernel to try to keep enough memory free to allocate 3 full        //Screen 32bpp buffers without entering direct reclaim.        intReserve = Displaywidth * Displayheight *4*3/1024x768;intReserve_adj = Resources.getsystem (). Getinteger (com.android.Internal. R.integer.config_extrafreekbytesadjust);intReserve_abs = Resources.getsystem (). Getinteger (com.android.Internal. R.integer.config_extrafreekbytesabsolute);if(Reserve_abs >=0) {reserve = Reserve_abs; }if(Reserve_adj! =0) {reserve + = Reserve_adj;if(Reserve <0) {reserve =0; }        }if(write) {Bytebuffer buf = bytebuffer.allocate (4* (2*moomadj.length +1)); Buf.putint (Lmk_target); for(intI=0; i<moomadj.length; i++) {Buf.putint (moomminfree[i]*1024x768)/page_size);            Buf.putint (Moomadj[i]);            } WRITELMKD (BUF); Systemproperties.Set("Sys.sysctl.extra_free_kbytes", Integer.tostring (reserve)); }//gb:2048,3072,4096,6144,7168,8192        //hc:8192,10240,12288,14336,16384,20480}
Change process weight adj value

In addition to the system's assessment criteria, we can also change the weight value of the process in our own way.

1. Writing files

?? Similar to the above mentioned Adj and minfree, process Oom_adj can also be modified by writing a file, the path is/proc/< PID >/oom_adj. For example, there are the following statements in Init.rc

on early-init # Set init and its forked children‘s oom_adj. write /proc/1/oom_adj -16

The PID 1 process is the INIT program, which sets the oom_adj of this process to 16, which guarantees that it will not be killed.

2. Set Android:persistent

?? For some very important programs, do not want it to be killed by the system. Add the "Android:persistent=true" attribute to the application tag in the Androidmainifest.xml file to set the application as resident memory, but it is important to note that if the application is not perfect, And the system can not be recycled normally, it will lead to unexpected problems.

Resources

Deep understanding of the Android kernel design idea

An explanation of Android memory management mechanism

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.