preface
Memory is a common problem, but it’s not getting enough attention for several reasons. 1. Memory issues are relatively subtle and not obvious 2. Android is also developed using the Jvm language and garbage collection is automatic, so there is generally no special concern 3. Memory problems are hard to locate, and often the problem is just a manifestation of the problem, and the real cause is hard to gather
The content of memory optimization is actually very complicated. We can try to understand 1 from the following ideas. To understand the memory problem, we first need to understand why memory optimization? 2. You also need to know some background knowledge about memory optimization, such as garbage collection 3. We need to understand some common tools and means of memory optimization 4. Picture is the focus of memory optimization, we need to focus on the knowledge of picture optimization 5. A direct embodiment of the memory problem is OOM. We also need to understand some means of OOM governance
So we can easily get to the main points of this article: 1. Why memory optimization? 2. Some background knowledge of Android memory optimization 3. Common tools and means of Android memory optimization 4. How to do picture memory optimization? 5. How to do OOM online monitoring?
The main contents of this paper are as follows:
1. Why memory optimization?
To answer this question, we should first clarify the requirements, what we are doing when we do memory optimization. The purpose of memory optimization is to reduce OOM rates, reduce lag, and increase application lifetime.
1.1 to reduceOOM
The rate of
A common reason for memory optimization is to reduce the OOM rate by applying too much memory and not releasing it in time, which often leads to OOM. There are various reasons for OOM, which will be discussed in detail later
1.2 Reduce congestion
There are a number of reasons why an Android interface can get stuck, one of which is memory. Memory problems affect interface fluency because of garbage collection. During GC, all threads are stopped, including the main thread. When both GC and drawing are triggered at the same time, the execution of the drawing is put on hold, causing frames to drop and the interface to get stuck.
1.3 Increasing the application lifetime
If an App is running in the background and using more memory, it will be cleared first. We usually want apps to survive as long as possible, so we should release memory as soon as it is no longer used
2. android
Some background on memory optimization
2.1 Java
Garbage collection mechanism
Java memory reclamation mainly includes the following contents: 1. Reachability analysis algorithm for determining whether objects are reclaimed 2. The Java garbage collection (GC) algorithm is used to collect garbage from the Java database. The Java garbage collection (GC) algorithm is used to collect garbage from the Java database
2.2 What is a Memory leak?
A memory leak is a block of memory that is not being used and cannot be usedGC
Reclaim, resulting in a waste of memory, for exampleHandler
Anonymous inner class holdsActivity
The reference,Activity
When it needs to be destroyed,GC
You can’t recycle it.
A memory leak is a gradual decrease in available memory and accumulation of memory that cannot be reclaimed until the application has no more available memory to apply for, resulting in memory overflow
The immediate cause of a memory leak is that a long-life object references a short-life object, making the short-life object unrecyclable
Common causes of memory leaks are:
1. Non-static inner classes hold external references
2. Static variables are heldcontext
A reference to the
3. Resources are not released in time
We typically use LeakCanary or Profile to detect memory leaks
2.3 What Is Memory Jitter?
Memory jitter occurs when we frequently create a large number of temporary objects in a short period of time, such as in afor
The image below is a representation of memory jitter. Its shape is zigzag, and the garbage can in the center represents a timeGC
.
Memory jitter means frequent object creation and collection, which can easily trigger GC, and all threads will stop during GC, which can cause stutter. To avoid memory jitter, we should avoid the following operations 1. Try not to create objects in the body of the loop. 2. Try not to create objects in the onDraw() method of a custom View, as this method will be called frequently 3. For objects that can be reused, consider using object pools to cache them
2.4 What is Memory Overflow?
Memory overflow Indicates that the requested memory exceeds the available memoryOOM
, which will cause our program to exit abnormally, which is also our focus indicator
causeOOM
There may be a variety of reasons, which can be divided into the following categories
aboutOOM
Management and online monitoring, etc., will be introduced in detail later
3. android
Common tools and means of memory optimization
3.1 Memory Profiler
Memory Profiler
isProfiler
In one of the sections,Profiler
是 Android Studio
Provides us with performance analysis tools to useProfiler
Analytical applicationsCPU
, memory, network, and power usage.
useMemory
The following functions can be tested
1. View the memory curve and memory usage
2. Locate memory jitter
3. Heap dump (Dump Java Heap
) objects that can detect memory leaks
aboutMemory Profiler
The specific use of is not described in this affix, want to know can refer to:What is a Memory Profiler?
3.2 Memory Analyzer Tool
The MAT tool can help developers locate objects causing memory leaks and find large memory objects, then solve memory leaks and reduce memory consumption by optimizing memory objects. MAT is more difficult to use than Memory profilers, and Memory profilers are becoming more powerful, so I don’t use MAT anymore. If you want to learn more about MAT, you can also see: What is The Memory Analyzer Tool
3.3 LeakCanary
Detecting memory leaks
Compared with theMemory Profiler
withMAT
.LeakCanary
More convenient in use
It’s easy to use to automatically detect memory leaks and alarm by simply adding dependencies to your project
When a leak occurs, the chain of references is as follows:
LeakCanary
It has the following characteristics:
1. Manual initialization is not required
2. Can automatically detect memory leaks and alarm by notification
3. Cannot be used online
LeakCanary
The detection process is as follows:
I have previously summarized the principle of LeakCanary in an article that anyone interested in LeakCanary can refer to: Learnwith Questions what you should know about LeakCanary2.0
3.4 Some general means of memory optimization
Some of the details of memory optimization can be avoided during development. Here are some general methods of memory optimization: 1) increase the maximum available memory by using the LargeHeap attribute; 2) remove the cache when the system triggers a resource stress callback; 3) use the optimized collection: 4) Carefully use SharedPreference,SP will load all contents into memory when the application is initialized, so it should not store large contents. 5) Carefully use external libraries, 6) Business architecture design should be reasonable. Abstraction can optimize the flexibility and maintainability of code, but it will also bring other costs, so it should be used in a balanced manner
These details are in fact very common, if you usually notice, I believe that the application of memory must be helpful
4. How to optimize image memory?
Memory optimization should give priority to where the effect is quick. Picture memory optimization is the focus of memory optimization. A picture may not be recycled and cause a waste of several meters of memory
4.1 Conventional image memory optimization methods
As we all know, image memory = wide high pixel occupied memory so optimize picture memory mainly have the following ideas 1. Zoom reduces the width and height. 2. Reduce the memory occupied by each pixel. 3. For large graphs, a strategy of partial loading can be adopted
4.1.1 Reduce image width and height
InSampleSize sometimes the image is 200 × 200 and the View is 100 × 100. In this case, if it doesn’t make sense to show 200 × 200 images, you should scale the image
BitampFactory.Options options = new BitmapFactory.Options();
// Set it to 4 to 1/4 the width and height of the image
options.inSampleSize = 4;
BitmapFactory.decodeSream(is, null, options);
Copy the code
4.1.2 Reduce the memory occupied by each pixel
In API29, Bitmap is divided into six levels: ALPHA_8, RGB_565, ARGB_4444, ARGB_8888, RGBA_F16 and HARDWARE.
ALPHA_8
: Does not store color information, each pixel occupies 1 byte;RGB_565
: only storesRGB
Channel, 2 bytes per pixel, rightBitmap
Color is not very demanding, can use this mode;ARGB_4444
To be abandoned or usedARGB_8888
Instead of;ARGB_8888
: Each pixel occupies 4 bytes and maintains high quality color fidelity. This mode is used by default.RGBA_F16
: Each pixel occupies 8 bytes, suitable for wide gamut andHDR
;HARDWARE
: a special configuration to reduce memory footprint and speed upBitmap
In the drawing.
Each level also takes up different bytes per pixel and stores different color information. For the same 100 pixel image, ARGB_8888 takes up 400 bytes and RGB_565 only takes up 200 bytes, so in some scenarios, changing the image format can reduce memory by half
4.1.3 Memory overcommitment to avoid repeated memory allocation
Bitmap occupies a large amount of memory. If we create and recycle Bitmap frequently, it is easy to cause memory jitter, so we should try to reuse Bitmap memory
At the beginning of the Android 3.0 (API level 11), system introduced BitmapFactory. Options. InBitmap field. If this option is set, the decoding method using Options objects attempts to reuse inBitmap when generating the target Bitmap, which means that inBitmap memory is reused, improving performance, while removing memory allocation and unallocation. However, inBitmap can be used with some limitations. Before Android 4.4 (API level 19), only bitmaps of the same size can be reused. After Android 4.4, the size of inBitmap can be larger than the target Bitmap
4.1.4 Big picture local loading policy
There is also a case for image loading where a single image is very large and does not allow compression. For example, display: world map, Qingming River map, weibo long map and so on do not compress, according to the original figure size loading, then the screen is certainly not big enough, and taking into account the memory, can not be a one-time whole map loading into memory so this kind of optimization idea is generally local loading, through BitmapRegionDecoder to achieve
// Set the center area to display the image
BitmapRegionDecoder bitmapRegionDecoder = BitmapRegionDecoder.newInstance(inputStream, false);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
Bitmap bitmap = bitmapRegionDecoder.decodeRegion(new Rect(width / 2 - 100, height / 2 - 100, width / 2 + 100, height / 2 + 100), options);
mImageView.setImageBitmap(bitmap);
Copy the code
4.1.5 summary
These memory optimization strategies for Bitmaps are relatively simple, and we probably don’t use them much in development because they are already encapsulated in image frameworks like Glide, So in general, we do not need to do these special operations when loading pictures, Glide has done what optimization for loading pictures, interested students can refer to: [with questions] Glide has done what optimization?
4.2 Picture bottom strategy
In view of the foractivity
,fragment
Leak caused the picture leak we can inonDetachedFromWindow
The timing is monitored and the specific process is as follows:
In this way, the cause can be conveniently solvedActivity
The resulting picture leakage problem
4.3 Online big picture monitoring scheme
When operating the online configuration is not reasonable size of the image, if we discover in time, may cause memory problems If the size of the image itself is not reasonable, on this basis we talk about the picture optimization also does not make sense, so this is also a larger image monitoring more common requirements Here are several large image monitoring plan:
4.3.1 ArtHook
plan
The scheme is implemented by epic library written by Weishu, through hook of ART virtual machine, setImageBitmap of Hook ImageView and other methods to analyze and compare the bitmap width and height of the method parameters and the width and height of ImageView instance. You can also get the actual size of the Bitmap. If the image is larger than the ImageView width, or the image size exceeds the threshold, you can report the information
The advantages of this scheme lie in: 1. The invasion is very low, the initial configuration can hook the global target View control 2. The code call stack is available for quick location by developers
The disadvantages are: compatibility problems, the use of HOOK system API, can not be used online
4.3.2 BaseActivity
plan
Most application projects in the process of business development will precipitation encapsulation of their BaseActivity, through the BaseActivity onDestroy dynamic detection of each View control, so as to know the picture loading situation
class BaseActivity : Activity() {fun onDestory(a){
if(isOpenCheckBitmap){
checkBitmapFromView()
}
}
fun checkBitmapFromView(a){
//1. Loop through the View controls in your activity
// Get the Bitmap loaded by View control
//3. Compare Bitmap width and height with View width and height}}Copy the code
The advantages of this scheme are: 1. Strong compatibility without any reflection; 2
Disadvantages are: 1. It is too intrusive and needs to modify BaseActivity; 2.BaseActivity
4.3.3 ASM
plan
The scheme inserts inserts in the compilation process and inserts Bitmap size detection logic by matching key methods such as setImageBitmap and setBackground. The advantages of this scheme are as follows: 1. Piling at compile time is non-invasive to the development process
Disadvantages are as follows: 1. The insertion of piles may increase compilation time; 2.ASM code is expensive to maintain and not so convenient to use
4.3.4 registerActivityLifecycleCallback
plan
Through registerActivityLifecycleCallback to monitor the Activity life cycle, when the onStop Bitmap size detection logic
private fun registerActivityLifecycleCallback(application: Application) {
application.registerActivityLifecycleCallbacks(object :
Application.ActivityLifecycleCallbacks {
override fun onActivityStopped(activity: Activity) {
checkBitmapIsTooBig(childViews)
}
})
}
Copy the code
This scheme is non-invasive to the original code, and it is relatively simple to use and has no compatibility problems. Therefore, it should be a better scheme
5. How to doOOM
Online surveillance?
As we described above, LeakCanary can be used offline to detect memory leaks, but LeakCanary can only be used offline and has the following problems 1. Offline scenes can run to the scene is limited, it is difficult to exhaust all user scenes. 2. During the detection process, GC needs to be triggered actively, and the app freezes due to memory mirroring Dump, resulting in bad experience during the test. 3. 4. Hprof files are too large, and it will cost a lot of resources to upload them as a whole
Below we introduce kuaishou open source online OOM monitoring framework KOOM
5.1 onlineOOM
Monitoring frameworkKOOM
introduce
We have described above why LeakCanary cannot be used for online monitoring, so the following issues need to be addressed in order to enable online monitoring
- monitoring
- Take the initiative to trigger
GC
, will cause a deadlock
- Take the initiative to trigger
- collect
Dump hprof
, can causeapp
freezeHprof
The file is too large
- parsing
- The parsing takes too long
- Parsing itself has
OOM
risk
Its core process consists of three parts:
1. MonitorOOM
When a problem occurs, memory image collection is triggered for further analysis
2. Collect the memory image, which is technically called heap dump, and copy the memory data to a filedump hprof
3. Analyze image files, conduct reachability analysis on leakage, super-large objects and other objects that we are concerned about, and resolve their resultsGC root
To solve the problem
5.2 KOOM
To solveGC
caton
LeakCanary detects whether an object is recovered by multiple GC, causing performance loss. Koom triggers image collection by monitoring the memory threshold without performance loss. The specific policies are as follows:
Java
The number of heap memory/threads/file descriptors exceeds the thresholdJava
The collection is triggered when the heap rise rate exceeds the threshold- happen
OOM
If policies 1 and 2 do not match, the collection is triggered - Leak determination is delayed until parsing
We do not need to determine whether an object is leaking at run timeActivity
For example, we don’t need to determine if it leaks at run time,Activity
There’s a member changemDestroyed
In theonDestory
Will be set to zerotrue
, as long as reachable and is found during parsingmDestroyed
fortrue
theActivity
, can be determined as leakage
This is resolved by delaying leak determination until parsingGC
Caton’s question
5.3 KOOM
To solveDump hprof
freezeapp
Dump hprof
That is, the vm needs to be paused to ensure that the reference relationship does not change during the process of copying the memory data to disk. The pause time is usually more than 10 seconds, which is unacceptable to usersLeakCanary
One of the most important reasons for not officially recommending online use.
usingCopy-on-write
Mechanism,fork
The child processdump
Memory mirroring is the perfect solution to this problem,fork
Upon success, the parent process immediately resumes the VM and the child process resumesdump
Memory mirroring is not affected by changes in the parent process data.
The process is as follows:
KOOM
Random collection of online memory images of real users, commondump
andfork
The child processdump
The blocking time is as follows:
It can be seen that the basic acquisition of memory image without perception can be achieved
5.4 KOOM
To solvehprof
The file is too large
Hprof
Files are usually large and analyzedOOM
Is 500M abovehprof
Documents are not unusual, the size of the documents, anddump
The success rate,dump
Speed and upload success rate are negatively correlated, and large files waste a lot of disk space and traffic.
So there’s a need forhprof
Crop and keep only the analysisOOM
In addition, clipping also has the benefit of data desensitization, only upload in-memory class and object organization structure, not upload real business data (such as strings,byte
Array and other contents containing specific data), to protect user privacy.
tailoringhprof
The document refers to thehprof
The understanding of file format will not be described here
Here is a flow chart of the clipping process:
5.5 KOOM
To solvehprof
Parsing time andOOM
Analyzing the hprof file, analyzing the reachabability of key objects and obtaining the reference chain is the core step to solve OOM. The previous monitoring and dump are paving the way for the analysis. There are two kinds of parsing, one is to upload the hprof file to be parsed by the server, and the other is to upload the report after being parsed by the client (usually only a few KB). KOOM opted for on-side parsing, which has two advantages:
- 1. Save user traffic
- 2. Use the user’s idle computing power to reduce
server
Stress, which also fits with the idea of distributed computing.
This can break down the parsing process into the following two problems
- Which objects need to be analyzed, all the analysis performance is too expensive, difficult to complete on the end, and the problem is not focused and not conducive to solving.
- Performance optimization as a
debug
Components, which have very high performance requirements for parsing without impacting the user experience.
5.5.1 Determination of key Objects
KOOM only analyzes the key object, which can be classified into two categories. One is the object that has been leaked and holds a large number of resources according to the rules. The other is the object whose shallow/retained size exceeds the threshold. For strongly reachable activity objects, determine that they are exposed when mDestroyed is true (onDestroy). Similarly, for fragments, when mCalled is true and mFragmentManager is null, the fragment is considered to have been leaked.
Bitmap/window/array/sufacetexture judged to be the second check the number of Bitmap/texture, high width, number of Windows, the length of the array, and so on is more than the threshold, coupled with the hprof related business information, such as screen size, View size, etc.
5.5.2 Performance Optimization
KOOM
inLeakCanary
Parsing engineshark
Based on some optimizations, will parse time inshark
Optimized on the basis of more than 2 times, memory peak control within 100M. Summarize the parsing process with a diagram:
The detailed process is not described here, the details can be seen:KOOM resolution performance optimization
5.6 KOOM
use
KOOM
Currently open source, open source address:Github.com/KwaiAppTeam…
Refer to the access guide. If the memory exceeds the threshold or occursOOM
, the memory snapshot collection is triggered. Yeshprof
The file is clipped and analyzed for a report
KOOM
The report isjson
Format, and size inKB
Level, the style is as follows:
This probably includes the following information
1. Some class information that may be leaked
2. Causes of leakagegcRoot
, the number of leaked instances, etc
3. Reference chain of leakage object to facilitate problem location
It can be seen that the amount of data uploaded by KOOM is not very large, but it is relatively accurate, which is very convenient for us to analyze online data
5.7 summary
This chapter mainly introduces the open source framework of online monitoring OOM KOOM. In fact, the framework of online monitoring OOM has been developed by various manufacturers, such as Probe of Meituan and Liko of Byte. However, most of them are not officially open source, but some articles introduce the principle, and interested students can also understand it
conclusion
As for the general direction of optimization, we should give priority to the areas with quick results, mainly including the following parts: 1. Memory leakage 2. Memory jitter 3.Bitmap monitoring 4
We also introduce various utilities for memory optimization 1. You can use Profile,MAT to locate memory jitter and memory leaks during development 2. Offline development, regression, Monkey, and pressure test can automatically integrate LeakCanary to detect memory leaks. 3. Picture loading is the focus of memory optimization. We can combine picture bottom-of-the-pocket strategy and online large picture monitoring to optimize picture memory problem 4. When the memory exceeds the threshold, the system automatically dumps the memory snapshot, and analyzes OOM problems accurately by uploading analysis results.
Memory optimization is a complex process. In the process of memory optimization, we need to combine a variety of tools, online and offline, and cooperate systematically to locate and solve problems
The resources
Probe into the Android memory optimization method (purgatory level – under) more elegant detection of Android applications in the large picture Kuaishou client stability system construction Douyin Android performance optimization series: Java memory optimization