Android Official Development Document Training Series course in Chinese: app memory management

Source: Internet
Author: User
<span id="Label3"></p><p><p>Original Address: http://android.xsoftlab.net/training/articles/memory.html</p></p><p><p>Random memory (RAM) is a very important area in any operating environment, especially in memory-constrained mobile operating Systems. Although Android's Dalvik virtual opportunity to recycle it, This does not mean that the app can ignore the requested and freed Memory.</p></p><p><p>In order for the garbage collector to effectively clean up the memory space occupied by the app, you need to prevent a memory leak from occurring and need to release the reference object at the appropriate Time. For most apps, the garbage collector frees the memory it consumes after the correct object is Used.</p></p><p><p>This lesson will learn how Android manages app processes and memory space, and how to reduce memory usage.</p></p>How Android Manages memory<p><p>Android does not provide dedicated memory swap space, but it uses paging and memory-mapping to manage memory. This means that any memory that you modify-whether or not used by the Object's allocation, or consumed by the memory Map-will remain in memory and cannot be swapped Out. So the only way to completely release app memory is to release any object references you might have, so that the garbage collector can recycle it. however, There is one exception: any file mappings that are not modified, such as code, are moved out of RAM when the system needs it.</p></p>Shared memory<p><p>To meet all the requirements in ram, Android tries to share Ram pages between Processes. It is implemented in several ways:</p></p> <ul> <ul> <li>Each app process is forked out by a process called Zygote. The zygote process starts when the system starts loading generic framework code and resources, such as the subject of the Activity. In order to start a new app process, the system will fork out the zygote process before loading and running the App's code in the new Process. This makes it possible to share the RAM pages that are allocated for Android framework code and resources between app Processes.</li> <li>Most of the static data is mapped to the PROCESS. This way, not only can you share data between processes, but you can also remove pages when you need Them. static data contains: The Dalvik code (placed in a pre-linked. odex file), the app resource, and the local code in THE. so File.</li> <li>In many places, Android shares the same block of RAM across different processes through an explicit memory allocation Area. For example, Windowsurface uses shared memory between the app and the screen synthesizer, and Cursorbuffer uses shared memory between the content provider and the Client.</li> </ul> </ul><p><p>Because of the large amount of shared memory used, it is necessary to check the memory space occupied by the app.</p></p>Allocation and recycling of memory<p><p>Here are some scenarios for Android memory recycling and Redistribution:<br>-the heap for each process in Dalvik has a virtual memory range limit. This range depends on the definition of the logical heap size, which can grow with the needs of the app (although the maximum will only grow to the amount of memory allocated by the system to each app).<br>-the logical size of the stack is not the same as the amount of physical memory used by the STACK. When the system checks the heap of the app, a value named proportional Set Size (pss) is computed, and PSS means that the list of pages that are shared with other processes that need to be cleaned up. For more information on pss, please read the guide: investigating Your RAM Usage.<br>-the Dalvik Stack's logical space on the stack is not continuously arranged, meaning that Android does not defragment the heap space. Android only organizes the Stack's logical space when the used space reaches the end of the Stack. however, This does not mean that the physical space used by the heap cannot be collated. After garbage collection, Dalvik scans the heap and finds useless pages, and then uses Madvise to return the pages to Kernel. therefore, the allocation of pairs, the recovery of large memory can make a large amount of memory to Reuse. however, the efficiency of recovering small pieces of memory can be very low, because the pages of a small piece of memory may be in use and have not been released.</p></p>Detect application Memory<p><p>To maintain a multi-tasking environment, Android sets a hard limit on the heap size of each app. The exact heap size is different, depending on the size of the Ram. If the app has run out of allocated heap capacity and continues to request more memory, the app will receive a OutOfMemoryError Error.</p></p><p><p>In some cases, you may need to know how much heap memory is available in your current device. For example, it is safe to check how much data cache space is in Memory. You can do this with the Getmemoryclass () method. It returns an integer value that, in megabytes, represents the available value for the app heap Memory. This content will be discussed in detail BELOW.</p></p>App switching<p><p>When the user switches the app and does not use swap space, Android places the process that switches to the background in an LRU (least recently used) cache. so, the user first opened an app, then there will be a process for it to start, and then the user left the app, but the app does not exit the process, then the system will cache the App's process, so if the user returned to the app again, then the newly cached process will be reused To complete a quick switchover.</p></p><p><p>If the app contains a cache process and consumes memory that is not needed by the current system, it can affect the overall performance of the system when the user is no longer using it. therefore, as the System's available memory decreases, The system may kill the least recently used process in the LRU Cache. To make the app cache as long as possible, the following sections describe when references should be Released.</p></p><p><p>For information about how more processes are cached in the background and how Android determines which processes should be killed, see: Processes and THREADS.</p></p>How the app should manage memory<p><p>Apps should consider the limitations of RAM at each development stage, including the design phase of the app. Several effective solutions are listed Below:</p></p><p><p>At development time, you should use the following methods to increase the efficiency of memory usage.</p></p>Use the service as little as possible<p><p>If the app needs to use the service to do some work in the background, never do unnecessary work within the SERVICE. Also note that after the work is done, if the service stops failing, beware of the disclosure of the Service.</p></p><p><p>When the service is started, the system holds a process for the Service. This makes the system expensive because the memory used by the service is not used for it. This reduces the number of processes that the system maintains in the LRU cache and makes the app less efficient to Convert. It can even cause the system to become stuck when the memory is very tight or the system cannot guarantee that there are enough processes to maintain the current number of Services.</p></p><p><p>The best solution for these problems is to use Intentservice to limit the number of local Services.</p></p><p><p>Leaving the service running is a <strong>very bad memory management error</strong> common to the app when the service is no longer needed. So don't covet to keep the service running long. Not stopping the service in time will not only increase the risk of insufficient app Ram capacity, but also make the user feel that the app is doing very poorly, and by the way uninstall it.</p></p>Freeing memory when the UI is not visible<p><p>When the user switches to another app, your app UI becomes invisible, so all the resources related to the UI should be Freed. Releasing UI resources in a timely manner can significantly increase the ability of the system to cache processes, which directly affect the User's experience.</p></p><p><p>In order to be able to receive system notifications after the user leaves the ui, the Ontrimmemory () method should be implemented within the Activity. In this method, listen for the Trim_memory_ui_hidden flag, which indicates that the UI is currently in a hidden state and should release all resources used by the UI.</p></p><p><p>Note here that the Trim_memory_ui_hidden flag represents all the UI components within the app that are hidden from the User. This is to be separated from the OnStop (), which is called when the Activity's instance becomes invisible when it is switched between the App's internal Activity. So although the resources of the activity such as network connections, logoff of broadcast receivers, etc. are released in OnStop (), the UI resources are generally not freed within the Method. Because this allows the user to return to the activity, the UI site can be recovered Quickly.</p></p>Freeing memory when memory is tight<p><p>At any stage of the app life cycle, the Ontrimmemory () method informs the current device that the memory is Tense. You should further release the resources when you receive the following flags:</p></p> <ul> <ul> <li>The Trim_memory_running_moderate app is currently running and will not be killed for the time being, but the device is currently in a low-memory state and the system is killing processes in the LRU Cache.</li> <li>The Trim_memory_running_low app is currently running and will not be killed for the time being, but the device is currently in very low memory running state, so you should free up useless resources to improve the performance of your System.</li> <li>The Trim_memory_running_critical app is still running, but the system is ready to kill most of the processes in the LRU cache, so the app should immediately release all unnecessary resources. If the system does not get a sufficient amount of RAM space, the system clears all processes in the LRU and kills some of the services that the host is Doing.</li> </ul> </ul><p><p>also, you may receive the following flag when the app is in the cache state:</p></p> <ul> <ul> <li>The Trim_memory_background app is in a low-memory running state, and the App's process is in the front of the LRU List. While the app is at a lower risk of being killed, the system may be ready to kill the LRU Process. The app should free up resources that are easy to recover, so the process will remain in the cache list and will recover quickly when the user returns to the app.</li> <li>The Trim_memory_moderate app is in a low-memory run, and the App's process is in the middle of the LRU List. If the System's memory is lowered further, the app's process may be killed.</li> <li>The Trim_memory_complete app is in a low-memory running State. If the system does not have enough memory, the App's process will be the first to be Killed. Apps should release everything that doesn't matter when you restore your app.</li> </ul> </ul><p><p>Because the Ontrimmemory () method is added to API 14, you can use Onlowmemory () to be compatible with the old version, which is roughly equivalent to the Trim_memory_complete flag.</p></p> <blockquote> <blockquote> <p><strong>note:</strong> When the system starts to kill the process in lru, although it is working from the bottom up, the system will still consider a situation in which the process consumes more memory, so if you kill the process, you will get more memory. So when the app is in the LRU cache, it consumes as little memory as possible, so the chances of keeping it in the cache list are large before it can be quickly restored when switching back to the app.</p> </blockquote> </blockquote>Check how much memory should be used<p><p>As we mentioned earlier, the RAM space for devices running Android is different, so the heap space provided to each app is Different. You can use the Getmemoryclass () method to get free space for your app. If the app tries to request a memory space that is larger than the value returned by the method, it will receive a outofmemoryerror Error.</p></p><p><p>In some particularly special environments, you can apply for a larger heap space, which can be set by adding largeheap= "true" properties to the < application> tag of the manifest File. After setting up, you can query the amount of stack space in large size by Getlargememoryclass ().</p></p><p><p>however, apps that apply for a lot of space should only be used for normal use, such as the big photo editing app. You should not do this because you often have outofmemory mistakes, what you should do is to solve the outofmemory Problem. This should only be done if you know for sure that the normal heap space is not enough to support the App's Runtime. Using additional memory space can seriously compromise the overall user experience, because the garbage collector consumes more time and the system performance slows down significantly during task switching or other concurrent Operations.</p></p><p><p>In addition, the size of large piles of space is not equal on all Devices. When running on a device with some RAM restrictions, the size of the large heap space may be equal to the normal heap space size. so, even if you apply for a lot of space, you should still use Getmemoryclass () to check the size of the regular heap, and try to control the amount of memory below this Range.</p></p>Avoid wasting the memory of bitmaps<p><p>When loading a picture into memory, it is best to adapt the picture to the current screen resolution size before doing the memory cache, if the original image itself is very high resolution, it is best to narrow it to fit the screen resolution SIZE. Note that as the bitmap resolution increases, the corresponding memory is increased as Well.</p></p> <blockquote> <blockquote> <p><strong>note:</strong> before Android 2.3.x, bitmap objects appear in the heap at the same size, regardless of the resolution, because the actual pixel data of the bitmap is stored separately in local memory. This makes debugging of bitmap memory allocations difficult because most of the stack analysis tools do not detect the allocation of local memory. however, since Android 3.0, bitmap pixel data has been allocated to the App's Dalvik stack, which improves the efficiency of garbage collection and debugging Capabilities.</p> </blockquote> </blockquote>Using an optimized data container<p><p>We recommend using the Android framework to optimize data containers such as sparsearray,sparsebooleanarray, and longsparsearray. regular hashmap is actually inefficient because it needs to create a separate entity for each mapping. In addition, Sparsearray is more efficient because it avoids the System's automatic boxing of keys or values.</p></p>To have a sense of memory consumption<p><p>Be fully aware of the language you use and the memory overhead of your library, and keep that awareness in mind, including in the app design Phase. Things that are often superficial seem harmless, but in fact they consume very high memory. Like what:</p></p> <ul> <ul> <li>The enumeration type of Java needs to occupy twice times the memory of the static Constant. You should resolutely stop using enumerations in ANDROID.</li> <li>For each class in java, the code that contains the anonymous inner class takes up to 500 bytes.</li> <li>An instance of each class takes up to 12-16 bytes of RAM Space.</li> <li>Putting each instance into HashMap requires an extra 32 bytes of Space.</li> </ul> </ul><p><p>Although the above content will only consume a few bytes of space, but they will be in the Program's internal rapid accumulation increases, become a Big Mac Overhead. It puts you in a very awkward position when analyzing memory problems, because these many small objects consume a lot of memory.</p></p>Beware of abstract Code<p><p>Often developers use abstract code to implement a good programming structure, because abstract code can improve the flexibility and maintainability of Code. however, Abstract code can be expensive: typically they require more code execution, more time and more RAM space to map these abstract code to Memory. so, if not necessary, it's best to stay away from Them.</p></p>Using a Nano-buffer protocol for serialized data<p><p>Protocol buffers is the data of a serialized structure designed by Google. It is language-independent, platform-independent, extensible. Similar to xml, but smaller, faster, and Simpler. If you decide to use the Nano-buffer protocol, you should always use it in your client Code. Regular protobufs generate very verbose code, which leads to quite a few problems: increasing memory consumption, increasing the size of the apk, slowing execution efficiency, and quickly approaching the limit of the Dex Flag.</p></p>Avoid relying on annotation frames<p><p>It is quite convenient to use annotation-dependent frameworks such as Guice and roboguice, because they simplify the writing of code and provide the appropriate test Environment. however, These frameworks do a lot of initialization when scanning the annotations of the code, which can cause a lot of code to be mapped into ram, even though you don't need to drop the code to load in Memory. These mapped pages will always reside in memory, although the system can purge them, but only if the pages reside in memory for long periods of time.</p></p>Use Third-party libraries Be careful<p><p>Third-party code is typically not written specifically for mobile Devices. When the code runs on a mobile client, it is often inefficient to perform. Before you decide to use a third-party library, you should assume that you are performing an important porting effort and will be burdened with maintenance and optimization of your mobile device. Analyze the size of the library and the usage of RAM before deciding to use it.</p></p><p><p>Even though some libraries are designed specifically for android, they are still a hidden problem because each library does something different. For a chestnut, a library might use a nanometer-sized protobufs, while the other library would use a millimeter-sized protobufs. Now two levels of PROTOBUFS have been used in the app. Both of these differences can occur in logs, parsing, image loading frameworks, caches, and anything else you don't expect.</p></p><p><p>Also beware of the pitfalls of falling into shared libraries, a common feature of this shared library is that you only use the small features that the library provides, and you don't want to put a lot of other code that you don't use into your project. In the end, if you are not particularly in need of this third party libraries, then the best way is to achieve one yourself.</p></p>Optimize Overall performance<p><p>Recommendations for overall app performance optimization are listed in best practices for performance. These recommendations also include CPU performance optimizations, in addition to memory optimizations such as reducing the number of layout objects.</p></p><p><p>You should also read the article about the optimizing your ui, which contains layout debugging tools and some of the layout tuning recommendations that are suggested in the lint Tool.</p></p>Use Proguard screen to remove useless code<p><p>The Proguard tool can achieve a streamlined, optimized, fuzzy effect by removing useless code and renaming class names, attributes, and methods in a meaningless name. You must then use the Zipalign tool to adjust the renamed Code. If you do not do this, you will greatly increase the amount of RAM used, because things like resources are no longer mapped to memory by the APK.</p></p> <blockquote> <blockquote> <p><strong>author Ps:</strong> This passage is excerpted from the introduction of zipalign, equivalent to saying zipalign principle and advantage: specifically, it causes all uncompressed data within The. apk, such As images or raw files, to is aligned on 4-byte Boundaries. This allows all portions to is accessed directly with mmap () even if they contain binary data with alignment Restrictions. The benefit is a reduction in the amount of RAM consumed when running the Application.</p> </blockquote> </blockquote>Analyze the use of RAM<p><p>Once the app reaches a relatively stable level, the next step is to analyze the App's RAM usage over each Lifecycle. For information on how to analyze RAM usage for your app, see: investigating Your Ram Usage.</p></p>Using multi-process<p><p>If it works for your app, another upgrade recommendation that might help you manage your app's memory is to deploy components to different processes. Use of this advice must always be particularly careful, and most apps should not use this technology, and if handled improperly it will quickly increase the consumption of Ram. This technique is extremely useful for apps that run in the background as important as the work in the foreground and can be managed separately.</p></p><p><p>The most suitable scenario for using multiple processes is the music player. If the entire app is running in a single process, most of the memory allocations performed by the activity UI will remain the same time as the music playback, even when the user switches to another app. Then an app like this should have two processes: one process is responsible for the ui, and the other is the ongoing running of the background service.</p></p><p><p>You can implement a standalone process by adding the Android:process attribute to the component in the manifest file that needs to execute a separate process. For example, You can add this property to a service that needs to perform a separate process and declare the Process's name "background" (you can name whatever you want):</p></p><pre class="prettyprint"><pre class="prettyprint"><code class="language-xml hljs "><span class="hljs-tag"><<span class="hljs-title">service</span> <span class="hljs-attribute">android:name</span>=<span class="hljs-value">".PlaybackService"</span> <span class="hljs-attribute">android:process</span>=<span class="hljs-value">":background"</span> /></span></code></pre></pre><p><p>The name of the process should begin with a colon ': ' to ensure that the process belongs to the private process of your app.</p></p><p><p>Before you decide to create a new process, you should understand the impact of Memory. To demonstrate the performance of each process, the first thing to consider is that a process that doesn't do anything takes about 1.4MB of memory space, and the following shows the empty state of the memory information heap:</p></p><pre class="no-pretty-print">adb shell Dumpsys meminfo com.example.android.apis:empty** meminfo in pid 10172 [com.example.android.apis:empty] * * PSS PSS shared private Shared private heap heap total clean Dirty Dirty Clean Clean Size Alloc free------------------------------------------------------ Native Heap 0 0 0 0 0 0 1864 1800 Dalvik heap 764 0 5228 3 0 0 5584 5499 Dalvik other 619 0 3784 448 0 0 Stack 28 0 8 0 0 other dev 4 0 0 0 4. So mmap 287 0 2840 212 972 0 apk mmap 0 0 0 136 0. Dex mmap 250 148 0 0 3704 148 other mmap 8 0 8 8 A 0 Unknown 403 0 6 00 380 0 0 Total 2417 148 12480 1392 4832 152 7448 7299 148 </pre> <blockquote> <blockquote> <p><strong>note:</strong> How to read this information can be found in investigating Your RAM Usage. The key data here is the memory indicated by private dirty and private Clean. They show that the process uses about 1.4MB of Non-swap page memory, while the other 150K RAM is the space occupied by the code that will be executed after being mapped to Memory.</p> </blockquote> </blockquote><p><p>It is important to understand the memory footprint of the empty process state and it will grow rapidly as the work Begins. For example, here is a memory footprint of the activity that shows some text:</p></p><pre class="no-pretty-print">* * Meminfo in PID 10226 [com.example.android.helloactivity] * * PSS PSS shared private shared private Heap heap Total clean Dirty Dirty clean clean Size Alloc free--- ---------------------------------------------------Native Heap 0 0 0 0 0 0 Dalvik Heap 1074 0 4928 776 0 0 5744 5658 2951 Dalvik Oth ER 802 0 3612 664 0 0 Stack 0 8-0 0 Ashmem 6 0 0 0 0 other Dev 108 0 104 0 4. So mmap 2166 0 2824 1828 3756 0 apk mmap 0 0 0 632 0. TTF mmap 3 0 0 0 0. Dex mmap 292 4 0 0 5672 4 other mmap 10 0 8 8 68 0 Unknown 632 0 412 624 0 0 Total 5169 4 11832 4032 10152 8 8744 8609 134</pre><p><p>The process now uses just three times times the memory, which will be nearly 4MB, just showing a piece of text in the Ui. This can be a very important conclusion: if you put the App's functionality in more than one process, only one process is used to respond to the ui, while the other process should avoid touching the UI because it can quickly increase RAM Consumption. Once the UI is drawn, it is almost impossible to reduce the amount of memory Used.</p></p><p><p>In addition, when running more than one process, it is important to make the code as thin as possible, because any unnecessary overhead is due to the same implementation being copied into each process. For example, if you are using enumerations (although you should not use enumerations), all of the Process's RAM needs to be created and initialized with the constants copied into each process, and any other abstract adapters, constants, or other memory-hogging will be Copied.</p></p><p><p>Another worry about using multiple processes is the dependency between Them. For example, If the app contains contentprovider, and the ContentProvider runs on the process that displays the ui, then the code for the other background process needs to use this contentprovider, which requires that the UI process is also loaded into Ram. If your service is a background service that is fairly weighted with the UI process, then the service should not rely on contentprovider or services in the UI Process.</p></p> <p><p>Android Official Development Document Training Series course in Chinese: app memory management</p></p></span>

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.