This paper is transferred to the direction of memory optimization

preface

Recent review of the past projects and learning in some memory optimization methods discussed and summarized. Android devices are getting more and more ram, and 4GB of ram is pretty common on phones, but you can’t get the most out of your apps unless you control the ram. So controlling memory is still an important technical metric for Android apps.

Let’s start with memory. Memory is a familiar concept, but can you tell the difference between mobile phone memory and computer memory? Is there a difference in memory between phones? Is the memory large enough?

  • What is mobile phone memory?

They are essentially the same, DDR memory on computers and LPDDR memory on mobile devices. The Full English name of LPDDR is Low Power Double Data Rate, LP is Low Power consumption, specially used for mobile electronic products. Compared with DDR4 memory in the PC field, LPDDR4 memory saves more power.

  • Phone memory differences?

Now the main running memory are LPDDR3, LPDDR4 and LPDDR4X respectively.

  • Is it good to have large memory?

In fact, we can conclude from the above point. An 8GB LPDDR4X phone will generally perform better than a 12GB LPDDR3 phone. But memory is not an isolated concept, it is related to the operating system, the application ecosystem and so on. I’m sure you were also impressed by the IPhone6 a few years ago when 1GB of ram was enough to make a 4-6gb Android phone. AndroidQ will perform better than Android4.0 for the same amount of memory. Closed spec IOS is better than open Android.

Common misconceptions about

Most people have a rough idea of what a phone’s memory is, which is a stack and a heap, but it’s actually a lot more complicated.

Explain the ins and outs of memory optimization

Let me just mention two common pitfalls

  • Objects can be loaded as long as they are smaller than memory space. Okay?

I once encountered a problem, when LOADING a 5MB image into the interface, I forgot to compress it and OOM appeared. But when I checked the log, I found that the available heap memory was clearly larger than 5MB, why OOM?



CMS
Continuous space



The threshold


  • So the less memory the better?

This is also one of the mistakes many people have, and even some people when memory is a monster, the less you use the better, so that it is easy to optimize excessive other problems. Now the development of mobile phone memory is more and more, if there is only a specific value, it is not necessary to make a hard indicator. Whether an APP takes up too much memory depends on the device, performance, and the situation at the time. You can make high-end devices use more memory and use different memory allocation and reclamation strategies depending on the performance of the device.

Direction of memory optimization

  • Memory hierarchical optimization

To optimize the device, a good architecture is required, which supports the following points:

  1. Device classification: Devices are classified using a device-year-class policy. For low-end users, complex animations or certain functions can be disabled. Use 565 format images, use smaller cache memory, etc. In the real environment, not every user’s equipment is as high-end as our test machine. In the development process, we have to learn to think whether the function should be opened on the low-end machine, and whether we can degrade when the system resources are tight

  2. Cache management: We need a unified cache management mechanism that can properly use memory; When “the system is in trouble”, it is obligatory to return it. We can use the OnTrimMemory callback to decide how much memory to free based on different states. For large projects, there may be dozens or hundreds of modules. Unified cache management can better monitor the cache size of each module.

  3. Process model: an empty process will occupy 10MB memory, and some applications have more than a dozen processes started, and some applications have been upgraded from two-process live to four-process live, so it is very important to reduce the number of applications started, reduce resident processes, and moderate live, for low-end machine memory optimization.

  4. Package size: The size of the code, resources, images, and so libraries in the package have a lot to do with the amount of memory they take up. An 80MB app will have a hard time running smoothly on a 512MB phone. In this case, we need to consider launching lightweight versions for low-end users, such as QQ Music HD, Kuaishou speed version, Toutiao speed version are this idea.

  • Bitmap optimization

Image resource memory generally accounts for a large part of the total memory of APP, so memory optimization can never avoid the “eternal theme” of image memory. Even if all bitmaps are put into Native memory, it does not mean that the image memory problem is completely solved, it just improves the system memory utilization and reduces some of the problems caused by GC. So how do we optimize image memory? I recommend the following two methods:

  1. Unified photo library

The premise of picture memory optimization is to close up the picture call so that we can do the overall control strategy. For example, low-end machines with 565 format and more stringent scaling algorithms can use Glide, Fresco, or take your own. All bitmap. createBitmap and BitmapFactory interfaces need to be further closed.

  1. Unified monitoring

Once the image library is unified, it is very easy to monitor Bitmap usage. There are two main points to note here.

  • Large image monitoring: We need to pay attention to whether the memory footprint of an image is too large, for example, the length is much larger than the View or even the width of the screen. In the development process, if you detect an irregular image usage, you should immediately pop up a dialog box to prompt the Activity and stack where the image is located, so as to find and solve the problem more quickly. In grayscale and online environments, anomaly information can be reported to the background, and we can calculate the proportion of images that exceed the screen size, which is the image’s “overwidth ratio.”
  • Analyzing total image memory: By collecting image usage, we can also count the memory occupied by all images of the application, so that online image memory usage can be analyzed according to different dimensions such as system, screen resolution and so on. When OOM crashes, you can also write the total memory occupied by pictures and the memory of Top N pictures into the crash log to help us troubleshoot problems.

After talking about device sizing and Bitmap optimization, we found that architecture and monitoring need to be done in two ways. A good architecture can reduce or even avoid mistakes, while a good monitoring can help us find problems in time.

  • A memory leak

Memory leakage is simply understood as the failure to recycle unused memory in time. Troubleshooting and solving memory leakage is also one of the unavoidable tasks of memory optimization. There are two main types of memory leaks: the same object leaks, or worse, new objects leak every time, with hundreds or thousands of useless objects. A lot of memory leaks are due to poor framework design, various singletons are flying around, and the lifetime of controllers in MVC is much longer than that of views. Good framework design can reduce or even prevent programmer mistakes, which is not always easy, so we also need to establish constant monitoring for memory leaks.

1. Java memory Leak: Establish an automated detection solution similar to LeakCanary, at least for Activities and Fragments. During development, we wanted to pop up a dialog when a leak occurred to make it easier for developers to find and fix the problem. Memory leak monitoring is not easy to put online. We can optimize the generated Hprof memory snapshot file by clipping most of the byte array corresponding to the image to reduce the file size. For example, a 100MB file is usually only 30MB after clipping, but less than 10MB after 7ZIP compression, which increases the success rate of file uploading

2. OOM monitoring: Meituan has Probe, an Android memory leak automatic link analysis component. It generates Hprof memory snapshot when OOM occurs and further analyzes this file through a separate process. However, it is still risky to use this tool online. Creating a memory snapshot during a crash may lead to a secondary crash, and it may take several minutes for some phones to create a Hprof snapshot, which will have a great impact on users’ experience. In addition, part of OOM is caused by insufficient virtual memory, which needs specific analysis.

3.Native Memory leak monitoring: In WeMobileDev’s article “wechat Android Terminal Memory Optimization Practices”, wechat tries some of these monitoring solutions.

4. For the case that SO cannot be reprogrammed: PLT Hook interceptor library memory allocation function is used, wherein PLT Hook is a scheme of Native Hook. After redirecting to our own implementation, we record the allocated memory address, size, source so library path and other information, periodically scan whether the allocation and release are matched, and output the recorded information for the unmatched allocation.

5. In the case of remarshable SO, all functions are staked by GCC’s “-finstrut-functions” parameter, and the stack on and out operation is simulated in the pile; The ld’s “– wrap” parameter intercepts the memory allocation and release function, redirects it to our own implementation and records the allocated memory address, size, source SO and the current contents of the call stack of the peg record, periodically scans whether the allocation and release are paired, and outputs the information we recorded for the unpaired allocation.

  • The GC monitoring

You can also use debug. startAllocCounting to monitor Java memory allocation and GC in laboratory or internal scenarios. Note that this option has some impact on performance. Although it is still available, it has been deprecated by Android. By monitoring, we can get information such as the number and size of memory allocations and the number of GC launches.

long allocCount = Debug.getGlobalAllocCount(); 
long allocSize = Debug.getGlobalAllocSize();
long gcCount = Debug.getGlobalGcInvocationCount();
Copy the code

The above information does not seem to be easy to locate the problem, but after Android 6.0 the system can get more accurate GC information.

// Number of GC runs debug. getRuntimeStat("art.gc.gc-count"); // Total elapsed time for GC in milliseconds debug.getruntimestat ("art.gc.gc-time"); Debug.getRuntimeStat("art.gc.blocking-gc-count"); // Total time for blocking GC debug. getRuntimeStat("art.gc.blocking-gc-time");
Copy the code

Special attention needs to be paid to the number and duration of blocking GC, as it suspends the application thread and can cause the application to stall. We can also count application scenarios in finer granularity, such as key scenarios such as login, startup, and main service.

Common optimization methods

Common optimization methods such as handler, WebView, memory jitter, anonymous memory class and so on there are many online will not be introduced. You are advised to refer to the full analysis of Android memory optimization to explore the method of Android memory optimization

conclusion

Before we optimize memory, how much do we need to optimize? What exceptions and delays are generated in memory? Only after the status quo and optimization goals of the APP are clear, can we proceed to the next step. When discussing the idea of memory optimization, we hope to give users different experience for different devices and different situations of devices. Here I mainly talked about Bitmap memory optimization and memory leak detection, monitoring some methods. Hope to help you.

Refer to the article

Manage Your App’s Memory

Why GC when memory usage is low

This article addresses memory barriers

leakcanary