Android performance comprehensive analysis and optimization scheme research - almost the most comprehensive and practical in history

Written in the front, if you are at a loss in the face of complex animation effects, don't bother to read this article: LottieAndroid uses detailed explanation and source code analysis - easily realizes various complex animations

This article is a comprehensive performance analysis and optimization scheme based on our product mobile phone Xunlei. This article is long, covers almost all performance problems, and gives solutions on how to find and solve problems. It is almost the most comprehensive and practical Android performance analysis and optimization article in history.
In addition, due to Jianshu's support for MarkDown, the picture format looks a bit messy, please forgive me and read it carefully.

Combining the following four parts to explain:

  • Classification of performance problems

  • Performance Optimization Principles and Methods

  • Analyze and solve problems with performance optimization tools

  • Performance Optimization Metrics

Classification of performance problems

1. Rendering problems: over-drawing, complicated layout

2. Memory problems: memory waste (memory management), memory leaks

3. Power consumption problem: power consumption

Performance Optimization Principles and Methods

1. Principles of performance optimization

  • Adhere to performance testing ( development and testing students have slightly different testing methods ): Do not rely on feeling to detect performance problems and evaluate the effect of performance optimization. You should maintain enough measurements and speak with data (mainly for testing students). Use various performance tools to test and quickly locate problems (mainly for development students).

  • Use low-end equipment: the same procedure, in low-end equipment, the same problem will be exposed more obviously.

  • Weigh the pros and cons: optimize on the premise of ensuring product stability and completing requirements on time.

2. Optimization method

  • Understand the problem ( divided into perceptible and imperceptible performance problems ): For performance problems, this step is only applicable to some obvious performance problems, and many imperceptible performance problems need to be located through tools. For example: memory leaks, level clutter, overdrawing, etc. are not perceptible. Swipe lag is perceptible.

  • Locating problems: Use tools to detect and analyze data to locate where there are performance problems.

  • Analyze the problem: After finding the problem, analyze how to solve the problem and determine the solution.

  • Solve problems: Find solutions based on analysis results.

  • Validation issues: Ensure that the optimization is effective, that no new issues are created, and that the product is stable.

performance optimization tool

The following optimization tools are described in detail in the following articles.

1. Mobile developer options : Debug GPU overdraw, enable strict mode, display CPU usage, GPU rendering mode analysis, display all "application not responding". (The name in the developer options of Xiaomi mobile phone development)

2. In IDE : Android Studio, such as static code detection tool, Memory Monitor, CPU Monitor, NetWork Monitor, GPU Monitor, Layout Inspector, Analyze APK, etc.

3. In SDK : sdk\tools, such as DDMS, HierarchyViewer, TraceView, etc.

4. Third-party tools : MAT, LeakCanary, GT, etc.

Performance Optimization Metrics

1. Rendering

  • Sliding fluency: FPS, that is, Frame per Second, the number of refresh frames in one second, the closer to 60 frames, the better;

  • Overdraw : 3X ( pink area) Overdraw for a single page is less than 25%

  • Startup time: The main point here is the startup time of the Activity interface, which is generally less than 300ms , and a high-frequency camera needs to be used to calculate the time.

2. Memory

  • Memory size: the lower the peak value, the better, it needs to be compared before and after optimization

  • Memory leak: need to use tools to check before and after optimization

3. Power consumption

  • The power loss per unit time, the less the power loss, the better. There is no fixed standard in the industry . Huawei has machines that specifically test power consumption, as well as its own standards.

1. Rendering problems

Let's take a look at the common causes of application UI freezes.

1. Artificially doing slight time-consuming operations in the UI thread, causing the UI thread to freeze;

2. The layout is too complicated to complete the rendering within 16ms;

3. The animation is executed too many times at the same time, which causes the CPU or GPU to be overloaded;

4. The View is overdrawn, causing some pixels to be drawn multiple times in the same frame time, thereby overloading the CPU or GPU;

5. View frequently triggers measure and layout, resulting in excessive time-consuming of measure and layout and frequent re-rendering of the entire View;

6. The memory frequently triggers too many GCs (memory is frequently created in the same frame), resulting in temporary blocking of rendering operations;

7. Redundant resources and logic cause slow loading and execution;

8. The notorious ANR;

The main source of performance problems such as stuttering that most users perceive is because of rendering performance. (Google official said)

The Android system sends a VSYNC signal (vertical synchronization -- field scan synchronization, field synchronization, vertical synchronization) every 16ms to trigger the rendering of the UI. If each rendering is successful, the 60fps required for a smooth screen can be achieved. In order to Able to achieve 60fps, which means that most operations of the program must be completed within 16ms (1000/60 = 16.67ms).

If one of your operations takes 24ms, the system will not be able to render normally when it gets the VSYNC signal, which will cause frame loss. Then the user will see the same frame within 32ms.

 

 

 

1. Overdraw

Overdraw describes the fact that a pixel on the screen is drawn multiple times in the same frame time . In a multi-level UI structure, if the invisible UI is also doing drawing operations, this will cause some pixel areas to be drawn multiple times. This wastes a lot of CPU and GPU resources, and finds out that the interface sliding is not smooth, the interface startup speed is slow, and the mobile phone is hot.

  • How to see overdraw?

    Settings - In-Development Options - Debug GPU Overdraw

  • Let's take a look at the over-drawing and optimization effects in the grenade (there are still many pages to be optimized in the grenade)

     

     

     

  • What do the various colors in the picture above mean?

     

     

     

      每个颜色的说明如下:
    
      原色:没有过度绘制
      紫色:1 次过度绘制
      绿色:2 次过度绘制
      粉色:3 次过度绘制
      红色:4 次及以上过度绘制
    
  • What is the key to causing over-optimization? Extra background (Background)

  • The following examples illustrate:

    • 1、MainTabActivity

      Modify the background in the Theme of MainTabActivity

       

       

       

      Remove the background in the layout (main_activity_linerlayout.xml)

       

       

       

      If you don't set a theme for the current Activity, what is the default theme and what is the default theme background?

       

       

       

       

       

       

       



       

       

       

       

       

       

       

       

        可以在默认主题中添加通用主题背景
        <item name="android:windowBackground">@drawable/common_layout_content_bkg</item>
        去除背景
        <item name="android:windowBackground">null</item>
      
    • 2. In addition to the extra background in the layout, it is also possible to add extra background in the code.

       

       

       

      Looking at the layout code of the sharing popup, I found that there is only one background, but why is it overdrawn?

       

       

       

       

       

       

      Code modification (SharePlatformsDialog.java)

       

       

       

    • 3. The bottom layout of the pop-up window will not cause the pop-up window itself to be overdrawn

       

       

       

      The drawing of the pop-up window belongs to clipping drawing, not overlay drawing. The mask layer is the adjustment of transparency and brightness, not drawing a layer of gray.
      If we don't want to use the system dialog but customize a popup view, we need to consider overdrawing.

    • 4. When customizing the view, use the clipRect method of Canvas to control the area that each view refreshes each time, so as to avoid refreshing unnecessary areas and avoid the problem of transition drawing. You can also use canvas.quickreject() to determine whether it intersects with a rectangle, thereby skipping drawing operations in those non-rectangular areas. Reference: http://jaeger.itscoder.com/android/2016/09/29/android-performance-overdraw.html

  • Key summary of optimization methods and steps

      总结一下,优化步骤如下:
    
      1、移除或修改Window默认的Background
      2、移除XML布局文件中非必需的Background
      3、按需显示占位背景图片
      4、控制绘制区域
    

2. Layout optimization

The layout is too complicated, and the level of nesting is too deep, which makes drawing operations time-consuming and increases memory consumption.
Our goal is to flatten the hierarchy .

  • Suggestions for layout optimization:

    • The first suggestion: Use relative layout if you can use relative layout to reduce the level, otherwise use linear layout. Performance analysis of RelativeLayout and LinearLayout in Android, reference: http://www.jianshu.com/p/8a7d059da746#

    • Second suggestion: Use merge tag to merge layouts, which can reduce layout hierarchy .

    • The third suggestion: Use include tags to reuse layouts, and extract common layouts to make the layout logic clearer, but avoid misuse of include .

    • Fourth tip: Avoid creating unnecessary layout hierarchies. ( The most likely to happen! )

    • Fifth suggestion: use lazy control ViewStub to realize dynamic loading of layout

  • How to view code layout with tools?

    There is a tool called  Hierarchy Viewer in the Android SDK toolbox, which can analyze Layout at runtime.
    You can use this tool to find the performance bottleneck of Layout.
    Conditions of use of this tool: Simulator or Root version of the real machine.
    How to turn on this function: In AndroidStudio, Tools — Android — Android Devices Monitor
    Disadvantages of this tool: it is troublesome to use.

     

     

     

  • Take a look at the problems encountered in the project (MainTabAvtivity).

    • Use of merge tags

       

       

       

      Merge is not used, eg: XLTabLayout.java

       



       

       

      Use merge, for example: the entry UserAccountItem of the account information page

       

       

       

    • Problems caused by the use of include tags

       

       

       

       

       

       

    • Avoid creating unnecessary layers (MainTabActivity)

       

       

       

    • Use of ViewStub

      The biggest advantage of this tag is that it will only be loaded when you need it, and using it will not affect the performance of UI initialization.
      Usually, when we need to use a layout under certain conditions, it will be hidden by gone or invisible. In fact, although this method hides the layout, it still instantiates the layout when the interface is displayed. Using ViewStub can avoid wasting memory and speed up rendering.
      In fact, ViewStub is a View with a width and height of 0. It is invisible by default. Only by calling the setVisibility function or the Inflate function will the target layout to be loaded be loaded, so as to achieve the effect of delayed loading. The loaded layout is set via the android:layout attribute.

       

       

       

      When preparing the inflate ViewStub, call the inflate() method. You can also set the Visibility of ViewStub to VISIBLE or INVISIBLE, which will also trigger inflate. Note that using the inflate() method returns the root View of the layout file.

        ((ViewStub) findViewById(R.id.stub_import)).setVisibility(View.VISIBLE);
        // or
        View importPanel = ((ViewStub) findViewById(R.id.stub_import)).inflate();
      

      Inflate is triggered when setVisibility

       

       

       

      Note: The merge tag cannot be used in layouts loaded using ViewStub.

  • Take a look at the Space tag (not commonly used)

    The space tag can only occupy a place in the layout file without drawing . The Space tag has a corresponding java class Space.java. By reading the source code, it can be found that it inherits from View.java and overwrites the draw method. This method is empty, both The draw method of the parent class is not called, nor is its own code executed, which means that the class has no drawing operation, but the onMeasure method is called normally, indicating that it has width and height.
    The main function is to set the spacing. This label is not commonly used, often using margin or padding.

3. Introduce tools for viewing rendering performance

  • Analysis of GPU rendering mode (roughly locate the problem)

    Developer Options - GPU Rendering Mode Analysis - Select "Display as bar graph on screen"

     

     

     

    Android Developer Options - Analysis of Gpu Rendering Mode, refer to: http://www.voidcn.com/blog/gjy211/article/p-6210447.html
    There will be two long bars when the auto-playing video stops , there will be another one when the next video is played. There's a noticeable lag here.
    Player action (DefaultPlayerView.java - doPlay, player_auto_control_layout.xml):

     

     

     

      上图的E total time = 68 是播放器停止播放的时候耗费的时间。
    
      total time = 29 是播放器开始播放的时候耗费的时间。
      其中,大部分时间耗费在了 5total time = 18 上面,这个是inflate播放器界面的时候耗费的时间。
    

     

     

     

    Are all inflates time consuming, take a look at the account information page:

     

     

     

     

     

     

  • GPU Monitor

  • Enable strict mode (not just rendering performance)

    The screen flickers when the app performs a long operation on the main thread.
    Strict Mode debugging through code, reference: http://www.tuicool.com/articles/ueeM7b6

Second, the memory problem

1. Memory waste

Whether the program memory management is reasonable and efficient has a great impact on the performance of the application.
Recommended reading Android Performance Patterns - Season 3, reference: http://hukai.me/android-performance-patterns-season-3/

  • ArrayMap (not used in our project, used a lot in Android source code)

    Android has specially written some more efficient containers for mobile operating systems, such as ArrayMap and SparseArray.
    In order to solve the disadvantage that HashMap occupies more memory, Android provides ArrayMap with higher memory efficiency.

    • Let's take a look at the principle of HashMap

      The overall structure of HashMap is as follows:

       

       

       

      The process of determining the storage location:

      !()[http://img.hb.aicdn.com/16b2993c41a413b24470e1b9b74227674cd16fdb9a09-UTrZIe]

       

       

       

    • Let's take a look at how ArrayMap optimizes memory

      It uses two arrays to work internally, one of which records the sequence list after the key hash, and the other array records the Key-Value values ​​in the order of the keys, as shown in the following figure:

       

       

       

      When you want to get a certain value, ArrayMap will calculate the hash value after the conversion of the input key, and then use the binary search method to find the corresponding index of the hash array, and then we can directly access the required index in another array through this index. key-value pair.

       

       

       

      Since the memory footprint in ArrayMap is continuous and uninterrupted, how does it handle insertion and deletion operations? What is the difference between it and HashMap? What is the difference between the deletion and insertion efficiency between the two? See the image below, which demonstrates the properties of Array:

       

       

       

       

       

       

      The memory usage efficiency comparison chart between HashMap and ArrayMap is as follows:

       

       

       

      Compared with HashMap, ArrayMap is more efficient in looping.

       

       

       

      When to use ArrayMap?

        1、对象个数的数量级最好是千以内,没有频繁的插入删除操作
        2、数据组织形式包含Map结构
      
  • Autoboxing (avoid autoboxing)

    Autoboxing behavior also often occurs in containers like HashMap, and a large number of autoboxing behaviors will occur when adding, deleting, modifying and checking operations on HashMap. Both HashMap and ArrayMap have Autoboxing behavior when the key is of type int.

  • SparseArray (used more in the project--I will talk about how to use tools to find the places where SparseArray should be used and not used)

    In order to avoid Autoboxing behavior Android provides SparseArray, this container is used when the key is of type int .
    SparseBooleanMap, SparseIntMap, SparseLongMap and other containers, the key is int, and the value type is boolean, int, long and so on.

  • Enum (enumeration, more used in projects, should be avoided as much as possible)

    Enums often require more than twice as much memory as static constants. You should strictly avoid using enums on Android.
    Android officials strongly recommend not to use enums in Android programs.
    Regarding the efficiency of enums, see the discussion below. Suppose we have such a code, and the compiled dex size is 2556 bytes. On this basis, add some of the following code, which uses ordinary static constant correlation as the judgment value:

     

     

     

    After adding the above code, the size of the compiled dex is 2680 bytes, which is only 124 bytes more than the previous 2556 bytes. If you use enum instead, the situation is as follows:

     

     

     

    The size of dex after using enum is 4188 bytes, which is an increase of 1632 bytes compared to 2556, and the increase is 13 times that of using static int. Not only that, with enum, additional memory usage will be generated at runtime, as shown in the following figure:

     

     

     

  • Some recommended articles:

2. Memory leak

  • What is a memory leak?

    Some unused objects are held for a long time, so the memory cannot be released.

  • Where can memory leaks occur?

    • Inner class reference causes Activity to leak

      In Java, non-static (anonymous) inner classes implicitly reference the outer class object by default. A static inner class does not reference the outer class object.
      The most typical scenario is the Activity leak caused by the Handler. If there are delayed tasks in the Handler or the task queue waiting to be executed is too long, the Activity may leak because the Handler continues to execute.
      In order to solve this problem, the message and runnable object in the remove Handler message queue can be executed before the UI exits. Or use Static + WeakReference to achieve the purpose of disconnecting the reference relationship between Handler and Activity.
      For example, MainTabActivity - MainTabHandler:

       





       

       

      How to fix?

       

       

       

       

       

       

       

       

       

      Android Weak Handler: Handler library that can avoid memory leaks, reference: http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1123/2047.html

    • The Activity Context is passed to other instances, which may cause itself to be referenced and leaked.

      Consider using Application Context instead of Activity Context.
      For example: the global Dialog or Context is held by a singleton.

    • Static memory leaks

       

       

       

       

       

       

      There are also static variables holding the View, for example:

        private static View view;
      
        void setStaticView() {
            view = findViewById(R.id.sv_button);
        }
      
    • Note the logout of the listener (analyze an example with the tool later)

      regist is to unregist

    • Pay attention to whether the Cursor object is closed in time (also exists in the project, no longer listed)

    • Leaks caused by WebView (no research for the time being)

  • Use tools to analyze and locate memory leaks

    • Memory monitor

      Through MemoryMonitor, you can see that the memory of starting the grenade and entering the grenade is as follows (why did not do any operation and the memory has been increasing?):

       

       

       

       

       

       

      Analyze a memory leak through an example, the operation steps are as follows:
      start the grenade - enter the home page - switch the bottom tab to my tab - click the login pop-up window - log in successfully and return to the home page

       

       

       

       

       

       

    • MAT(Memory Analyzer Tool)

      You need to download the independent version of MAT, you can download and decompress it here: \\192.168.8.188\上传2\ltsoft
      Analyze the memory situation of the operation just now

       

       

       

       

       

       

       

       

       

      Entering the home page does not perform any activities, why are there so many bitmap objects?

       

       

       

    • LeakCanary

       

       

       

      LeakCanary Chinese instructions, reference: https://www.liaohuqiu.net/cn/posts/leak-canary-read-me/
      LeakCanary: Make memory leaks invisible, reference: https://www.liaohuqiu.net /cn/posts/leak-canary/

    • TraceView (without detailed analysis)

    • GT (should be more suitable for testing students to test APP performance)

      With GT, you can perform quick performance tests (CPU, memory, traffic, power, frame rate/fluency, etc.), view development logs, crash logs, Capture of network data packets, debugging of internal parameters of APP, time-consuming statistics of real machine code, etc.
      GT official website: http://gt.qq.com/index.html

  • Memory usage policy optimization

    • Look at downloading a video plus browsing the featured page, then switching the app to the background, memory usage

       

       

       

       

       

       

       

       

       

    • What are the strategies for optimizing memory

      • onLowMemory() : The Android system provides some callbacks to notify the memory usage of the current application. Generally speaking, when all background applications are killed, the forground application will receive the onLowMemory() callback. In this case, it is necessary to release the unnecessary memory resources of the current application as soon as possible to ensure that the system can continue to run stably.

      • onTrimMemory(int) : The Android system has also provided the onTrimMemory() callback since 4.0. When the system memory reaches certain conditions, all running applications will receive this callback, and parameters will be passed in this callback, representing Depending on the memory usage, when you receive the onTrimMemory() callback, you need to judge according to the type of parameters passed, and choose a reasonable choice to release some of your own memory. Apps that are judged by the system to be prioritized to be killed.

  • Recommended articles:

3. Recommended artifact for performance optimization (Lint)

  • How did you find the problems in some of the projects analyzed above?

    Lint: Static Code Analysis Tool

  • How to find issues in a project through Lint, how to use it?

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

  • If you only want to analyze the code of a certain folder

     

     

     

     

     

     

  • Set code analysis options

     

     

     

3. Power consumption problem

For example: turn off the login ping when the screen is turned off, and turn it back on when the screen is on.
Many of the above problems can lead to increased power consumption.
How to optimize the battery-consuming mobile phone overheating problem when downloading in the background?
Specific hardware tools are required to test the power consumption of the application, and a set of power consumption test standards is required.



Author: Li Tong Tookie
Link: https://www.jianshu.com/p/307ba8911799
Source: Jianshu
The copyright belongs to the author. For commercial reprints, please contact the author for authorization, and for non-commercial reprints, please indicate the source.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325249469&siteId=291194637