Dear students, Good morning, Monday. Today’s recommended article is from Allen children’s Shoes authorized reprint and share. The content of the article has been written in the title, so I will not repeat it here.

The original address: http://www.jianshu.com/p/9755da0f4e8f

When it comes to Android phones, most people have the impression that after using them for a period of time, they will become a little bit sluggish. Some programs will crash inexplicably during running. When opening the system folder, they find that there are many files. Even though the phone is way ahead of all the performance scoring apps, it feels like no amount of memory space is enough. I believe that every user who uses Android system has had the similar experience above. Indeed, Android system is not as smooth as iOS system. Why? There are many reasons for this phenomenon. A brief list of them is as follows:

  • In fact, in recent years, with the continuous iteration of Android version, The Android system provided by Google has become more and more smooth, the latest release is Android Oreo (8.0). However, Android phones used by most users in China are customized versions of major manufacturers, which are often not the latest native system kernel. Most of them may still stay on Android 5.0 system, and even Android 6.0 accounts for a small proportion, resulting in delays in updating.

  • Because the Android system source is open, everyone as long as comply with the corresponding agreement, you can modify the source code, then the domestic manufacturers will be based on Android source code transformed into their own external release system, For example, we are familiar with MIUI system of Xiaomi mobile phone, EMUI system of Huawei mobile phone and ColorOS system of Oppo mobile phone. Since every vendor has modified the source code of the Android native system, there will be a problem, which is the famous Android fragmentation problem, essentially different Android applications compatibility, not to achieve consistency.

  • Due to various Android fragmentation and compatibility problems, Android developers need to adapt to different systems when developing applications. At the same time, the development level of each Android developer is uneven, and the written application performance also has different types of problems, resulting in different user experience in the process of use. Then some problems with users will be translated into Android system problems, which will affect the evaluation of Android phones.

Performance optimization

Today I want to focus on Android APP performance optimization, which is to say what should be paid attention to when developing an application, how to better improve the user experience. In addition to attractive functions and interactions, a good application should also have high requirements on performance. Instant applications are very distinctive and may attract some users in the early stage of the product, but if the user experience is poor, it will also bring bad reputation to the product. So what defines a good app? There are three main aspects:

  • Business/Function

  • Logical interaction

  • Excellent performance

As we all know, Android system, as an operating system based on mobile devices, has certain limitations in hardware configuration. Although the configuration is becoming more and more advanced, it still cannot be compared with PC, and it uses unreasonable CPU and memory or consumes a lot of resources. You will encounter stability problems caused by insufficient memory, and problems caused by CPU consumption.

When faced with a problem, we all want to contact the user and check the log. However, it is hard to find the reason for the feedback about performance problems. Logs are mostly useless. Because performance problems are mostly non-essential, problem location is difficult to reproduce, and without critical logs, the cause cannot be found. These issues can affect the user experience and functionality, so it is important to understand some of the performance optimization solutions and optimize our application in real projects to improve the user experience.

Four aspects:

User experience performance issues can be summarized into four main categories:

  • smooth

  • stable

  • Save electricity and flow

  • The installation package is small

The main causes of performance problems are common and varied, but they boil down to memory usage, code efficiency, proper policy logic, code quality, package size, etc., sorted as follows:

As can be seen from the figure, building a high-quality application should aim at four directions: fast, stable, economical and small.

  • Fast: avoid lag, fast response speed, reduce user waiting time, meet user expectations.

  • Stability: reduce crash rate and ANR rate, do not crash and no response in the process of user use.

  • Save: save the flow and power consumption, reduce the user cost, avoid the use of hot mobile phone.

  • Small: The installation package is small to reduce the installation cost.

To achieve these four goals, the implementation is the question in the right border: Caton, memory usage is not reasonable, poor quality of the code, code logic, the installation package is too large, the problem is also one of the most serious problems encountered in the process of development, in the implementation needs of the business at the same time, also need to consider that spend more time to think, how to avoid the function to do optimization, after the completion of function such as otherwise after the implementation of maintenance costs will increase.

Caton optimization

Android applications are slow to start and often lag in use, which greatly affects user experience and should be avoided as far as possible. There are many scenarios of Caton, which can be divided into four categories: UI drawing, application startup, page skipping and event response, as shown in the figure below:

The root causes of these four stutter scenarios can be divided into two broad categories:

  • Interface drawing. The main reasons are the deep level of drawing, complex page and unreasonable refresh. Due to these reasons, the scene of lag appears more in UI, the initial interface after startup and the jump to the page drawing.

  • Data processing. The reason for this lag scenario is that the amount of data processing is too large, which can be divided into three situations: first, the UI thread is processing data; second, the main thread cannot get time slices due to the high CPU usage of data processing; third, the memory increase leads to frequent GC, which causes the lag.

There are many reasons for the lag, but no matter what the reasons and scenarios are, they are ultimately displayed on the device screen to reach users. In the final analysis, there is a problem with the display. Therefore, to solve the lag, we must first understand the display principle of the Android system.

Display principle of Android system

The Android display process can be summarized as follows: The Android application will cache the Surface data after measurement, layout and drawing, and render the data to the display screen through SurfaceFlinger, and refresh the data through the Refresh mechanism of Android. That is to say, the application layer is responsible for drawing, the system layer is responsible for rendering, and the data that the application layer needs to draw is transferred to the system layer service through inter-process communication, and the system layer service updates the data to the screen through the refresh mechanism.

We all know that there are three core steps in every View drawing on Android: Measure, Layout, and Draw. The specific implementation starts from the performTraversals() method of ViewRootImp class. Measure and Layout recursively obtain the size and position of the View, and take depth as priority. It can be seen that the deeper the hierarchy, the more elements, and the longer the time.

The SurfaceFlinger service is used in system-level processes to render data to the screen. What does the SurfaceFlinger service do? As follows:

  • In response to client events, Layer is created to establish a connection with the client Surface.

  • Receive client data and properties, modify Layer properties such as size, color, transparency, etc.

  • Flushes the Layer content created to the screen.

  • Maintain the Layer sequence and perform clipping calculations on the final output of the Layer.

Since there are two different processes, there must be a cross-process communication mechanism to achieve data transfer. In Android display system, anonymous shared memory of Android is used: SharedClient, a SharedClient is created between each application and SurfaceFlinger, and within each SharedClient, up to 31 SharedBufferStacks can be created. Each Surface has a SharedBufferStack, which is a Window.

A SharedClient corresponds to an Android application, and an Android application may contain multiple Windows, namely Surface. In other words, SharedClient contains a collection of SharedBufferStack, which uses double buffering and triple buffering techniques for display refresh. Finally, the overall process of display is divided into three modules: application layer drawing to the cache, SurfaceFlinger rendering the cache data to the screen, because it is different process, so use Android anonymous shared memory SharedClient cache the data to be displayed to achieve the purpose.

In addition, we need a noun: FPS. FPS means the number of frames transmitted per second. Ideally, the card would not be felt at 60FPS, which means that each drawing should take less than 16ms. But the Android system probably won’t be able to complete those complex page rendering operations in time. The Android system signals VSYNC every 16ms to trigger a rendering of the UI, which, if successful each time, should achieve the 60FPS required for smooth graphics. If an operation takes 24ms, the system will not be able to render properly when it gets the VSYNC signal, and frames will be lost. Then the user will see the same frame in 32ms, which is quite common when performing animation or sliding list. It may also be that your Layout is too complex, with too many layers of drawing units, which cannot complete rendering in 16ms, resulting in the delay of refreshing.

Caton root cause

According to the display principle of The Android system, it can be seen that the fundamental reasons affecting the drawing are as follows:

  • Drawing tasks are too heavy and it takes too long to draw a frame of content.

  • The main thread was too busy, and the data was not ready according to the VSYNC signal sent by the system, resulting in frame loss.

Drawing takes too long, and there are tools to help us locate problems. The main thread is responsible for handling user interactions, drawing pixels on the screen, and loading and displaying relevant data, so it’s especially important to avoid any main thread so that your application remains responsive to user actions. To sum up, the main thread does the following:

  • UI lifecycle control

  • System Event Handling

  • Message processing

  • Interface layout

  • Interface to draw

  • Interface to refresh

In addition, you should try to avoid putting other processing in the main thread, especially complex data calculations and network requests.

Performance analysis tool

Performance problems are not easy to reproduce or locate, but they still need to be solved. Then, you need to use the corresponding debugging tools to analyze the problem and confirm whether the problem is solved. For example, View Layout Hierarchy, GPU Profile tool on Android system and Static code inspection tool Lint. These tools play a very important role in performance optimization, so you should be familiar with them and know which tools to analyze in which scenarios.

1, Profile GPU Rendering

In mobile developer mode, there is a lag detection tool called Profile GPU Rendering, as shown below:

Its functional features are as follows:

  • A graph monitoring tool that can reflect the current drawing time in real time

  • The horizontal axis represents the time, and the vertical axis represents the time spent per frame

  • Refresh rendering from left to right over time

  • Provides a standard time. If the time is higher than the standard time, the current frame is lost

2, TraceView

TraceView is a built-in tool of the Android SDK. It is used to analyze function calls and perform performance analysis on Android applications and code in the Framework layer. It is a graphical tool, and will eventually produce a chart for performance analysis, which can analyze the execution time of each method, including the number of method calls, recursion times, actual time and other parameter dimensions, very intuitive to use, very convenient to analyze performance.

3. Systrace UI performance analysis

Systrace is a performance data sampling and analysis tool provided by Android 4.1 and above. It returns some information from a system perspective. It can help developers collect Android key subsystems, such as Surfaceflinger, WindowManagerService and other key Framework modules, services, View system operation information, so as to help developers more intuitive analysis of system bottlenecks, improve performance. Systrace’s features include tracking system I/O operations, kernel work queues, CPU load, etc., providing good data on UI display performance analysis, especially on issues such as poor animation playback, rendering cards, etc.

Optimization Suggestions

1. Layout optimization

Page layout is reasonable is the main influence of measuring the amount of time, we know that a page display measuring and drawing process is done through the recursion, quadtree traversal time related to tree height h, its time complexity is O (h), if the level is too deep, for every layer increases more page shows time, so the rationality of the layout is very important.

So what are the methods of layout optimization? Mainly through reducing levels, reducing measurement and drawing time, and improving reusability. The summary is as follows:

  • Reduce layers. Use RelativeLayout and LinerLayout wisely, and Merge wisely.

  • Improve display speed. With the ViewStub, it is an invisible view object that doesn’t take up layout space and has a very small footprint.

  • Layout reuse. Can be achieved by

    Tags to improve reuse.

  • Use wrAP_content as little as possible. Wrap_content will increase the calculation cost of layout measure. If the width and height are known to be fixed, wrAP_content is not used.

  • Removes unwanted properties from the control.

2. Avoid overdrawing

Overdrawing is when a pixel on the screen is drawn more than once in the same frame. In a multi-level overlapping UI structure, if the invisible UI is also drawing, some pixel areas will be drawn multiple times, thus wasting redundant CPU and GPU resources.

How to avoid overdrawing is as follows:

  • Layout optimization. Remove non-essential background from XML, remove Window’s default background, and display placeholder background images on demand

  • Custom View optimization. Use Canvas.cliprect () to help the system identify the visible areas within which it will be drawn.

3. Start optimization

By monitoring the startup speed, you can find problems that affect the startup speed and optimize the startup logic to improve the startup speed of applications. Startup does three things: UI layout, drawing, and data preparation. Therefore, starting speed optimization is to optimize these three processes:

  • The UI layout. Applications generally have flash screens. Optimize the UI layout of the flash screen, and you can detect frame loss by using Profile GPU Rendering.

  • Enable load logic optimization. You can use distributed loading, asynchronous loading, and deferred loading strategies to improve application startup speed.

  • Data preparation. Data initialization analysis, load data can be considered with thread initialization strategy.

4. Reasonable refresh mechanism

In the process of application development, pages need to be refreshed to display new data due to data changes. However, frequent refreshing will increase resource overhead and may lead to lag. Therefore, a reasonable refreshing mechanism is needed to improve the overall UI fluency. A reasonable refresh requires the following considerations:

  • Keep the number of flushes to a minimum.

  • Try to avoid having high CPU threads running in the background.

  • Zoom out the refresh area.

5, other

In the realization of animation effect, need to choose the appropriate animation frame according to different scenes to achieve. In some cases, hardware acceleration can be used to provide fluency.

Memory optimization

In The Android system, there is a garbage memory reclamation mechanism, which automatically allocates and releases memory in the virtual machine layer. Therefore, there is no need to allocate and release a certain piece of memory in the code. From the application layer, memory leakage and overflow are not easy to occur, but memory management is required. Android has a Generational Heap Memory model for Memory management, where most of the stress of Memory reclamation doesn’t need to be cared about by the application layer. It has its own management mechanism, and when Memory reaches a threshold, The system automatically frees whatever Memory it thinks it can, according to different rules, and because The Android program leaves Memory control to Generational Heap Memory, when there are problems with leaks and spills, it can be a tough job to check for errors. In addition, some Android application developers do not pay special attention to the rational use of memory in the development process, and do not do too much optimization in memory, when the application is running more and more tasks at the same time, coupled with more and more complex business requirements, Completely relying on The Memory management mechanism of Android will gradually lead to a series of performance problems, which can not be ignored to the stability and performance of the application. Therefore, it is necessary to solve the memory problem and reasonably optimize the memory.

Android memory management mechanism

Android applications are run on Android virtual machines, and the memory allocation and garbage collection of applications are done by virtual machines. On Android, virtual machines have two running modes: Dalvik and ART.

1. Java object life cycle

A typical Java object has seven runtime phases on the virtual machine:

Create Phase -> Application Phase -> Invisible Phase -> Unreachable Phase -> Collect Phase -> End Phase -> Object space reallocation phase

2. Memory allocation

In Android, memory allocation is actually allocating and freeing the heap. When an Android application is started, the application process is derived from a process called Zygote. After the system starts the Zygote process, the system generates a new process in order to start a new application process, and then loads and runs the application code in the new process. Most of the RAM Pages are used to assign to Framework code and to enable RAM resources to be shared among all application processes.

However, in order to control the memory of the entire system, the Android system sets a hard maximum Dalvik Heap Size threshold for each application, and the total threshold varies with the RAM Size on different devices. If an application tries to allocate memory when the memory usage is close to the entire threshold, it is easy to cause memory overflow errors.

3. Memory reclamation mechanism

Remember that in Java memory is divided into three regions: Young Generation, Old Generation, and Permanent Generation. Recently allocated objects are stored in the Young Generation area. Objects that do not collect garbage may be moved to the Old Generation according to different rules, and eventually move to the Permanent Generation region over a period of time. The system performs different GC operations depending on the memory data type in memory. GC determines whether objects are collected by determining whether they are referenced by live objects, and dynamically reclaims memory occupied by objects without any references. However, it should be noted that frequent GC will increase application stutter and affect application fluency. Therefore, it is necessary to minimize system GC behavior to improve application fluency and reduce the probability of stutter.

Memory analysis tool

Before memory optimization, we need to understand the current memory usage status of the current application, and analyze which data types have problems, how to analyze the distribution of various types, and how to find the specific objects causing the problems after discovering the problems. This requires relevant tools to help us.

1, the Memory of the Monitor

The Memory Monitor is a graphical tool used to Monitor the Memory usage of a system or application. It has the following functions:

  • Displays available and used memory, and displays memory allocation and reclamation in real time in terms of time.

  • Quickly determine whether an application’s slowness is due to excessive memory reclamation.

  • Quickly determine if an application is crashing due to lack of memory.

2, the Heap Viewer

The Main function of the Heap Viewer is to view the usage of different data types in memory. You can view the Heap Size of the current process, the types of data, and the proportion of each type of data. This data can be analyzed to find large memory objects, which can be further analyzed to reduce memory overhead through optimization, and memory leaks can also be found through changes in the data.

3, the Allocation of the Tracker

Both the Memory Monitor and Heap Viewer can intuitively and in real time Monitor Memory usage and find Memory problems. However, the cause cannot be further found after a Memory problem is found, or an abnormal piece of Memory cannot be distinguished from the normal one, and specific classes and methods cannot be located after the problem is found. In this case, you need to use Allocation Tracker, another memory analysis tool, for more detailed analysis. Allocation Tracker tracks the memory Allocation of applications, lists their call stack, and shows the cycle of memory Allocation for all objects.

4, Memory Analyzer Tool(MAT)

MAT is a rapid, feature-rich Java Heap analysis tools, through the analysis of the memory of a Java process snapshot HPROF analysis, from a host of object analysis, quickly calculate the size of the object in memory footprint, see which object can’t be recycled garbage collector, and can see visually through the view object could cause such a result.

Common memory leak scenarios

If fixing a memory leak after it has occurred can increase the cost of development, it is best to think about memory problems and write higher-quality code. Here are some common memory leak scenarios that should be avoided in future development.

  • The resource object is not closed. Cursors, files, etc., usually use some buffer, when not in use, should be closed.

  • The registered object is not logged out. For example, if an event is registered and not unregistered, a reference to the object is maintained in the observer list.

  • Class to hold large data objects.

  • A static instance of a non-static inner class.

  • Handler temporary memory leak. If the Handler is non-static, the Activity or Service will not be collected.

  • Memory leaks caused by objects in the container not being cleaned up.

  • The WebView. WebView has a memory leak problem. Once a WebView is used in an application, the memory will not be released.

In addition, memory leaks can be monitored, most commonly with LeakCanary third-party library, which is an open source library to detect memory leaks. It is very simple to use, alarms are generated when a memory leak occurs, and leak tarce is generated to analyze the location of the leak, and Dump files are provided for analysis.

Optimize memory space

No memory leaks, does not mean that there is no need to optimize memory, on mobile devices, because of limited storage space physical devices, the Android system for each application process were also given a limited heap memory, so using the minimum memory objects or resources can reduce the memory overhead, at the same time let the GC can more efficiently recovery and no longer need to use the object, Keep the application heap memory full of available memory to make the application run more stably and efficiently. Common practices are as follows:

  • Object reference. There are four reference types: strong reference, soft reference, weak reference, and virtual reference. You can select different reference types based on service requirements.

  • Reduce unnecessary memory overhead. Pay attention to automatic packing to increase memory overcommitment, such as effective utilization of system resources, view multiplexing, object pool, and Bitmap object multiplexing.

  • Use the best data type. For example, for data class container structures, you can use ArrayMap data structures, avoid enumerated types, use caching Lrucache, and so on.

  • Image memory optimization. You can set bitmap specifications, compress according to sampling factors, manage images with some image caching, and so on.

Stability optimization

The definition of stability of Android applications is very broad, and there are many reasons that affect the stability of applications, such as unreasonable memory usage, poorly considered code exception scenarios, unreasonable code logic, etc. Two of the most common scenarios are Crash and ANR. These two errors will make the program unusable. Common solutions are as follows:

  • Improve code quality. For example, code review during development, see some code design logic, business rationality, etc.

  • Code static scan tool. Common tools include Android Lint, Findbugs, Checkstyle, PMD, and more.

  • Crash monitoring. Record some crash information and abnormal information in time for subsequent analysis and solution.

  • Crash upload mechanism. After the Crash, try to save the log information to the local computer first and upload the log information when the network is normal next time.

Optimize the power consumption

In mobile devices, batteries are so important that nothing can be done without them. For OS and device developers, power consumption optimization has never stopped in pursuit of longer battery life, while for an app, it is not enough to ignore the power usage problem, especially those classified as “battery killer” apps, which ultimately end up being uninstalled. Therefore, application developers need to minimize battery consumption while fulfilling their requirements.

Before Android5.0, testing Battery consumption in an app was cumbersome and inaccurate, but since then an API has been introduced to retrieve information about Battery consumption on your device :Battery Historian. Battery Historian is an Android Battery Historian. Like Systrace, it is a graphical data analysis tool that visually displays the Battery consumption of a mobile phone by entering an application as an application Historian. Finally, some methods of electric quantity optimization are provided for reference.

In addition, there are some common solutions available:

  • Calculation optimization, avoiding floating point operations, etc.

  • Avoid improper use of WaleLock.

  • Use the Job Scheduler.

Package size optimization

The size of an application installation package has no effect on application usage. However, a larger application installation package has a higher threshold for users to download applications, especially on mobile networks, where users have higher requirements on the size of the installation package. Therefore, reducing the size of the installation package enables more users to download and experience products.

The composition of common application installation packages is shown in the figure below:

As can be seen from the picture:

  • Assets folder. Some configuration files and resource files are stored. The ID of assets is not automatically generated, but obtained through the interface of AssetManager.

  • Res. Res is short for resource. This directory stores resource files. Ids are automatically generated and mapped to.r files.

  • Meta-inf. Saves application signature information, which verifies the integrity of APK files.

  • Androidmanifest.xml. This file is used to describe the configuration information of the Android application, registration information of some components, permission to use, etc.

  • Classes. Dex. Dalvik bytecode program, which makes the Dalvik VIRTUAL machine executable. Generally, The Android application converts Java bytecode to Dalvik bytecode through the DX tool in the Android SDK during packaging.

  • Resources. Arsc. It records the mapping between resource files and resource ids to search for resources based on resource ids.

Common solutions to reduce the size of the installation package:

  • Code confusion. Use the ProGuard code obfuscator tool, which includes compression, optimization, obfuscation, and more.

  • Resource optimization. For example, using Android Lint to remove redundant resources, minimizing resource files, etc.

  • Image optimization. For example, use AAPT tool to compress the PNG image and reduce the color number.

  • Avoid duplicate libraries, use WebP image formats, etc.

  • The plug-in. For example, function modules can be downloaded on the server to reduce the size of the installation package.

summary

Performance optimization is not something that can be solved with one or two new releases. It is an ongoing requirement, continuous integration and iterative feedback. In the actual project, the project in the beginning, due to the manpower and time limit, the completion of the project performance optimization of lower priority, such as entered the stage of project put into use, it need to increase the priority, but at the beginning of the project, in the design of architecture, performance optimization point also needs into consideration, early this reflects a programmer technology.

When there is a demand for performance optimization, it usually starts from finding the problem, analyzing the cause and background of the problem, looking for the optimal solution, and finally solving the problem. This is also commonly used in daily work.

Like this article can long press to pay attention to the following TWO-DIMENSIONAL code, adhere to the Android development for you to recommend dry goods, like, forward the way can also support to this public number oh.

Past wonderful

  • Understand Java memory leaks once and for all

  • Android programmers are invited to contribute

  • I made an interview guide with some of my friends at BAT

  • Android city selector source code implementation