directory

  • One. Android rendering knowledge
    • 1.1 Drawing Principle
    • 1.2 frame drop
    • 1.3 why 60Fps?
    • 1.4 Garbage Collection
    • 1.5 the UI thread
    • 1.6 VSYNC
    • 1.7 UI drawing mechanism and rasterization
  • Ii. Detection and resolution
    • 2.1 Detection Dimensions
    • 2.2 Debugging Tools
    • 2.3 How to Solve the problem
  • 3. Overdrawing of the interface
    • 3.1 Over-drawing concept
    • 3.2 Tracking overdrawing
    • 3.3 The root of overdrawing
    • 3.4 Influence of unreasonable XML layout on rendering
    • 3.5 Source code
  • 4. Rendering performance
    • 4.1 Rendering performance concept
    • 4.2 Tracking rendering performance
    • 4.3 Causes of poor rendering performance
    • 4.4 Test Description
    • 4.5 Supplementary description of UI drawing mechanism
  • Five. Reasonable layout boundary
  • Vi. Suggestions for interface optimization for development
    • 6.1 Optimize the layout structure
    • 6.2 Optimizing the processing logic
    • 6.3 Make good use of the DEBUG Tool

One. Android rendering knowledge

1.1 Drawing Principle

Android requires each frame to be drawn within 16ms, and smooth completion of a frame means that any particular frame needs to execute all the rendering code (including the commands the framework sends to the GPU and the CPU to draw to the buffer) within 16ms, keeping the experience smooth. This speed allows the system to render at a smooth frame rate of about 60 frames per second (1 second / 0.016 frames per second = 62.5 frames per second) during animation and input events.

If your application does not draw the frame in 16ms, it will drop the frame if it takes you 24ms to draw the frame.

The system is ready to draw a new frame on the screen, but this frame is not ready, so there will be no drawing and the screen will not refresh. Feedback to the user is that the user stared at the same image for 32ms instead of 16ms, which means that frame drop occurred.

1.2 frame drop

Dropping frames is a very core problem in the user experience. If the current frame is discarded and the previous frame rate is not continued, this discontinuous interval will easily attract the attention of the user, which is often referred to as the lag and not smooth. There are many reasons for dropping frames, such as:

  • It took a lot of time to redraw most of the stuff in the interface, which was a waste of CPU cycles;
  • Excessive drawing, spending too much time drawing objects that the user can’t see;
  • There are a lot of animations repeated over and over again, consuming CPU and GPU resources;
  • Frequent triggering of garbage collection;

1.3 why 60Fps?

Android system requires each frame to be drawn within 16ms, so the frame rate of 1 second is about 60 frames per second (1 second / 0.016 frames per second = 62.5 frames per second), so why use 60 Fps as the standard to measure App performance? This is because the coordination between the human eye and the brain cannot perceive updates beyond 60 Fps.

The vast majority of Android devices on the market refresh their screens at 60 HZ. Of course, anything above 60 Fps is meaningless and the human eye can’t perceive the difference. 24 Fps is a continuous linear motion that the human eye can perceive, so it is the frame rate commonly used for film tape, because this frame rate is enough to support most of the content of the film, while minimizing the cost of the film. However, anything less than 30 Fps is not going to work, so 60 Fps is needed to achieve the desired effect.

The interface performance goal for your app is to maintain 60 Fps, which means you only have 16 ms per frame (1 second / 60 frame rate) to process all the tasks.

1.4 Garbage Collection

Garbage collector is a mechanism that automatically frees memory that is no longer referenced during application runtime, often referred to as GC. Frequent GC is also a major cause of serious performance problems.

As mentioned earlier, smoothly completing a frame means that all rendering code must be completed within 16ms. Frequent GC severely limits the amount of time left in a frame, and if the GC does more work than is necessary, there is less time to apply smooth framerates. The closer you get to 16ms, the more likely you are to get stuck when the garbage collection event is triggered.

Note that Android4.4 introduced a new ART virtual machine to replace the Dalvik virtual machine. Their mechanics are very different, in a nutshell:

  • The GC of the Dalvik VM is very resource-intensive, and under normal circumstances an Android device with good hardware performance can easily consume 10-20 ms;
  • The ART VIRTUAL machine’s GC dynamically improves the efficiency of garbage collection, with interruptions in ART, usually in 2-3 ms. Performance improvement over Dalvik VIRTUAL machine;

The ART virtual machine has a significant performance improvement over the garbage collection of the Dalvik virtual machine, but a collection time of 2-3 ms is sufficient to exceed the 16ms frame rate threshold. Therefore, while garbage collection is no longer a resource-intensive behavior after Android 5.0, it is always something to avoid if possible, especially in the case of performing animations, which can result in some frame loss that the user feels is obvious.

1.5 the UI thread

The UI thread is the main thread of the application, and a lot of the performance and lag issues are due to the amount of work we do in the main thread. Therefore, all the operation of consuming resources, such as IO operation, network operation, SQL operation, list refresh, etc., should be realized by background process, can not occupy the main thread, the main thread is the UI thread, is the key to keep the program smooth;

In Android version 5.0, the Android framework layer introduced “Render Threads” to send actual Render operations to the GPU. This thread relieves some of the UI thread reduction. But input, scrolling, and animation are still in the UI Thread, because the thread must be able to respond to operations.

1.6 VSYNC

Vsync is a new technology that Android4.1 has introduced into the UI architecture with Project Butter, along with Triple Buffer and HWComposer to improve UI fluency.

Generally speaking, the FRAME rate of the GPU should be higher than the refresh rate so as not to lag or drop frames. If the screen refresh rate is faster than the frame rate, the screen will display the same image in two frames, and when this stutter continues, the user will feel the animation stutter or drop frames, and then return to normal, often referred to as flicker, frame skip, delay. Apps should avoid these framerate drops to ensure that the GPU is able to fetch and write data before the screen refreshes to ensure smooth animation.

1.7 UI drawing mechanism and rasterization

Most rendering operations rely on two pieces of hardware: CPU and GPU. CPU is responsible for calculation operations of Measure, layout, Record and Execute, while GPU is responsible for Rasterization operations. View components that are not required can cause redundant CPU computation and use redundant GPU resources.

Rasterization can split resource components such as Button, Shape, Path and Bitmap into different pixels for display. This operation is time-consuming, so a GPU was introduced to speed up the rasterization operation.

The CPU is responsible for calculating the UI components into Polygons and textures, and then handing them to the GPU for rasterization rendering, and uploading the processing results to the screen for display.

The display of resource components in Android (Bitmaps, Drawable) is packaged together into a common Texture and then passed to the GPU.

The display of pictures is loaded into memory after calculation by CPU, and then transferred to GPU for rendering.

The text is first converted to Texture by CPU and then rendered to GPU. When the CPU draws a single character, the rendering content is re-referenced by GPU.

Animation display is more complex, we need to complete all CPU and GPU calculation, drawing, rendering and other operations within 16 ms, to obtain smooth application experience.

To detect and solve

2.1 Detection Dimensions

Depending on the business and the test granularity required, there are different dimensions of detection. At present, the interface performance testing dimensions required by my business are as follows:

  • Interface overdrawing; (Detect overdrawing)
  • Rendering performance; (Detect UI rendering performance in strict mode)
  • The layout boundary is reasonable; (Check the reasonableness of the element display)

Some user scenarios in specific tests may also contain other hidden detection dimensions, such as:

  • OpenGL tracking analysis;
  • GPU view update rationality;
  • Flash hardware layer updating rationality;
  • Animation acceleration/deceleration state problem spot detection;

2.2 Debugging Tools

Detection and resolution of interface performance issues will largely depend on your application architecture. Fortunately, Android provides a number of debugging tools, and it is important to know and learn how to use these tools to help you debug and analyze interface performance issues for a better application performance experience. Here are some common Android interface performance debugging tools:

2.2.1 Hierarchy View

Hierarchy View is built into the Android SDK and is used to check whether the View structure of an interface is too complex. It is used to know which views are over-drawn and how to improve them.

2.2.2 Lint

Lint is a static code scanning tool that comes with ADT to suggest improvements for unreasonable or risky modules in XML layout files and project code. The official tips for using Lint in practice are as follows:

  • Contains unnecessary branches, recommended to remove;
  • Contains useless parent controls, recommended to remove;
  • Warning The layout depth is too deep.
  • Compound drawables are recommended.
  • The merge tag is recommended.

2.2.3 Systrace

Systrace comes with Android DDMS and can be used to track graphics, View, and Window information to find some deep problems. Very troublesome, big limitation, the actual debugging I basically do not use.

2.2.4 Track

Track comes with Android DDMS, which is a great way to Track which methods take time to construct a view. It is accurate to every function, whether application function or system function. We can easily see where frames are dropped and how all functions are called in that frame, and find out the problem points for optimization.

2.2.5 OverDraw

By opening “Debug GPU overdrawing” in the developer option of the Settings APP on Android devices, you can view the overdrawing situation in all interfaces and branch interfaces of the application, which is convenient for optimization.

2.2.6 GPU presentation Mode Analysis

By enabling “GPU Rendering Mode Analysis” in the Developer option of the Android device Settings APP, you can obtain the rendering time of each frame of the last 128 frames to analyze the performance of rendering and performance bottlenecks. Official introduction to poke Me.

2.2.7 StrictMode

Check to see which APP actions are taking too long on the main thread by enabling “Strict mode” in the Developer option of the Settings APP on your Android device. When operations violate StrictMode, the screen will flash red and output StrictMode information to the LOGCAT log.

2.2.8 Animator duration scale

Speed up or slow down the animation time by opening “Window Animation Zoom”/” transition animation Zoom “/” Animation Program Duration Zoom “in the Developer options of the Android device Settings APP to see if there is a problem with the animation in the accelerated or slowed state.

2.2.9 Show hardware layer updates

By enabling “Show Hardware Layer updates” in the Developer option of the Settings APP on your Android device, Flash hardware layer updates will appear green. Using this tool allows you to see which layouts are updated during animations that you don’t expect to be updated, making it easier to optimize for better application performance. Optimizing Android Hardware Layers

2.3 How to Solve the problem

As mentioned above, the test dimensions required by our company are as follows:

  • Interface overdrawing; (Detect overdrawing)
  • Rendering performance; (Detect UI rendering performance in strict mode)
  • The layout boundary is reasonable; (Check the reasonableness of the element display)

Therefore, the following will focus on these three and two points, respectively, from the concept, tracking, digging root and troubleshooting tools to specifically describe how to solve, and to the development of optimization suggestions.

3. OverDraw the interface

3.1 Over-drawing concept

Overdraw is the term used to indicate that some components are drawn more than once at a pixel point on the screen.

Generally speaking, drawing interface can be likened to a doodler’s graffiti on a wall. Graffiti is a lot of work. Each point on the wall may be painted with various colors in the process of graffiti, but the final color can only be one. This means that the colours we spend so much time painting are not visible to passers-by, a waste of time, energy and resources, with a lot of room for improvement. In the same way, spending too much time drawing things that are stacked on the bottom and not visible to the user wastes CPU cycles and rendering time!

\

In the official example, cards that are activated by the user are at the top and those that are not activated are at the bottom, spending too much time drawing objects that the user can’t see.

3.2 Tracking overdrawing

By opening “Debug GPU overdrawing” in the developer option of the Settings APP on Android devices, you can view the overdrawing situation in all interfaces and branch interfaces of the application, which is convenient for optimization.

Android displays different shades of color on the screen to indicate overdrawing:

  • No color: No overdrawing, that is, a pixel is drawn once, and the display applies the original color;
  • Blue: 1 times overdrawn, that is, a pixel has been drawn twice;
  • Green: 2x overdraw, i.e. one pixel is drawn 3 times;
  • Light red: 3x overdrawn, i.e. one pixel has been drawn 4 times;
  • Deep red: 4 times overdrawn or more, that is, a pixel has been drawn 5 times or more;

The hardware performance of the device is limited, and performance degrades when over-drawing causes the application to consume more resources than are available, in the form of stuttering, poor flow, ANR, etc. To maximize the performance and experience of your application, you need to minimize overdrawing, which means more blue blocks rather than red blocks.

In practical tests, the following two points are commonly used as test indexes for over-drawing, and the over-drawing is controlled within an agreed reasonable range:

  • There is no more than 4X overdrawing (dark red area) on all app interfaces and branch interfaces.
  • For all interfaces and branch interfaces, 3X overdraw the total area (light red area) does not exceed 1/4 of the screen viewable area;

3.3 The root of overdrawing

Overdrawing comes largely from the problem of overlapping views, followed by unnecessary background overlap.

Official examples, such as an application all the View of the background, will look like the first picture, and after removing these unnecessary background (refers to the Windows default background, Layout of the background, the background of the text and images may be), the effect like the second picture, the basic not excessive.

3.4 Influence of unreasonable XML layout on rendering

The deeper the node tree of the layout file, the more tags and attributes are set in the XML, which can have a disastrous effect on the display of the interface.

To display an interface, the first step is to parse the layout. After requestLayout, a series of measure, layout and draw operations are required. If the layout file is too deeply nested and has too many label attributes, the execution time of each step will be affected. The display of the interface is only displayed after these operations, so each step of the operation time increases, the final display time will be longer.

Iv. Rendering Performance

4.1 Rendering performance concept

Rendering performance is often the culprit for frame drops, and it’s a common and frustrating problem. The good news is that Android gives us a powerful tool that makes it very easy to track down performance rendering issues and see what’s causing your app to stall and drop frames.

4.2 Tracking rendering performance

Open the “GPU Rendering Mode Analysis” option in the Developer options of the Settings APP on your Android device and select “Show as a bar chart on screen”.

This tool will display the latest 128 frames of GPU drawing data of the current interface on the screen of the Android device in real time, including StatusBar, NavBar and GPU drawing histogram data of the current interface. We generally only need to care about the graphics data drawn by the GPU on the current interface.

There are 128 small bar charts on the interface, which represent the latest 128 frames of GRAPHICS data drawn by GPU on the current interface. A small bar chart represents the rendering time of this frame. The higher the bar chart, the longer the rendering time. As the interface is refreshed, the bar chart information is also updated in real time.

There is a green line in the middle, representing 16 ms, and the key to keeping the animation flowing is to keep these vertical bars as far below the green line as possible, and any time you cross the green line, you risk losing a frame.

Each bar chart is made up of three colors: blue, red and yellow.

  • The blue is the time it took to draw the Display List for this frame. In plain English, it records how long it takes to update the view on the screen. In code language, this is the time to execute the view’s onDraw method and create or update the Display List for each view.

  • The red is how long it takes OpenGL to render the Display List for this frame. In plain English, it records the time it takes to perform a view drawing. In code language, it is the time that Android uses OpenGL ES API to render 2D Display List.

  • The yellow represents how long the CPU is waiting for the GPU to process this frame. In layman’s terms, it is the time that the CPU waits for the GPU to reply when it receives a command. In code language, this is a blocking call.

In practical tests, the following two points are commonly used as the test indexes of rendering performance to control the rendering performance within a agreed reasonable range:

  • Perform all functions and branch functions of the application, and keep at least 90% of the bar area involved in the operation below the green line;
  • From the perspective of user physical examination, it is subjective to judge whether the lag feeling in all operations of the application on the Android device with 512 M memory is acceptable and will not feel strange and abrupt.

4.3 Causes of poor rendering performance

When you see a higher blue line, it may be because your view suddenly doesn’t work and needs to be redrawn, or your custom view is too complex and takes too long.

When you see a high red line, it may be because your view has been resubmitted to be redrawn (for example, the current interface is recreated after the screen is rotated from portrait to landscape), or because the custom view is too complex to draw and takes too long. Such as the following view:

When you see a high yellow line, it means you’re giving the GPU too much work, too many responsible views to draw and process with OpenGL commands, and the CPU is waiting for the GPU to respond to the command.

4.4 Test Description

This tool is a great way to help you find rendering related issues, help you find performance bottlenecks that are stalling, and track down exactly what is causing the application under test to stall and slow down so you can optimize it at the code level. Even let the person in charge of product design improve his design for a good user experience.

Testing rendering performance is often accompanied by turning on “strict mode” to see which applied scenarios are taking too long to execute on the UI thread (the main thread).

Other powerful but perhaps less used tools aid analysis when testing performance renderings, such as:

  • HierarchyViewer: This tool is often used to see if an interface’s view structure is too complex, to see which views are overdrawn, and how they can be improved;
  • Tracer for OpenGL: This tool collects all the drawing commands sent by the UI to the GPU. Often used to help developers DEBUG and locate knottier rendering details that are beyond the HierarchyViewer tool.

4.5 Supplementary description of UI drawing mechanism

As mentioned above, layout and UI components are first calculated by CPU into Polygons and textures that CAN be recognized and drawn by GPU, and then handed to GPU for rasterization rendering, and the processing results are uploaded to the screen for display. The “CPU computes as an object that the GPU can recognize and draw” operation is done with the help of DisplayList. DisplayList has the data information to hand to the GPU to rasterize rendering onto the screen.

DisplayList is created the first time a view needs to be rendered. When the view needs to be re-rendered due to changes such as the position being moved, it is enough for the GPU to perform an additional rendering command to update the view to the screen. But if the contents of the drawing in the view change (for example, it is no longer visible), then the DisplayList between them can no longer be used, and the system will re-create the DisplayList, render the DisplayList, and update it to the screen. The performance of the process depends on the complexity of the view.

Optimize Advice for developing interfaces

6.1 Optimize the layout structure

Layout structures that are too complex can slow down rendering and cause performance bottlenecks. This can be optimized by following common and effective layout principles:

  • Avoid complex View hierarchies. The more complex the layout, the more bloated it is, the more likely it is to have performance problems, find the most resource-efficient way to present nested content;

  • Try to avoid using RelativeLayout layouts at the top of the view hierarchy. RelativeLayout relativelayouts are resource-intensive because a RelativeLayout RelativeLayout requires two measurements to ensure that it handles all layout relationships, and this problem gets worse as RelativeLayout relativelayouts grow in the view hierarchy.

  • If the layout level is the same, it is recommended to use a LinearLayout instead of a RelativeLayout LinearLayout, because the performance of a LinearLayout is higher. When you really need to lay out your branches relative to each other, consider a more optimized GridLayout that preprocesses the relationship of the branch views to avoid the double metric problem.

  • For complex layouts, use a RelativeLayout layout. With a RelativeLayout layout, you can easily implement a LinearLayout that can be nested.

  • Do not use AbsoluteLayout;

  • Reusable components are extracted and reused with labels. If a layout is used by a UI that applies to more than one place, write it as a layout widget for easy reuse across uIs. Official explanation: “Poke me”

  • Use the merge tag to reduce the nesting level of the layout.

  • Remove unnecessary invisible backgrounds. With multi-layer background color layout, only the top layer of visible color to the user can be left, other users can not see the bottom color can be removed, reduce invalid drawing operations;

  • Try to avoid using the layoutweight attribute. Using a LinearLayout with a layoutweight attribute requires each sub-component to be measured twice, which consumes too much system resources. This is especially important when using ListView tags and GridView tags, because child components are created repeatedly. The layout can be split using a 0dp view within a RelativeLayout layout. If not, then… ;

  • The proper layout structure of the interface should be wide and shallow, not narrow and deep;

6.2 Optimizing the processing logic

  • Load the view as needed. Some of the less reusable, resource-intensive views can be loaded when needed to improve UI rendering speed;

  • Use the ViewStub tag to load some unusual layouts;

  • The performance of dynamically inflation View is better than that of setVisiblity with ViewStub tag. Of course, it is more appropriate to use ViewStub tag to implement some functions.

  • Avoid unnecessary resource consuming operation and save precious operation time.

  • Avoid heavy operations on the UI thread. Consumption of resources (such as IO operation, network operation, SQL operations, lists, refresh, etc.) the operation of the consumption of resources application background processes to achieve, not to take up the UI thread, the UI thread is the main thread, the main thread is the key to keep the program smoothly, should only operate the core UI operation, such as processing view attributes and drawing;

  • Minimize arousal. We often broadcast to receive messages and events that we expect to respond to, but too many responses can consume excess Android device performance and resources. Therefore, the wake up mechanism should be minimized, and when the application does not care about these vanishes and events, it turns off broadcasts and carefully chooses which intents to respond to.

  • Consider low-end devices, such as 512 MEgabytes of RAM, dual-core CPUS, and low resolution, and make sure your application can accommodate all levels of devices.

  • Optimize application startup speed. When an application launches an application, feedback from the interface as soon as possible gives the user a good experience. For faster startup, you can lazily load some UI and avoid initializing code at the Application level.

6.3 Make good use of the DEBUG Tool

  • Use some of the debugging tools provided by Android to track the performance of your app’s key features.
  • Use some of the debugging tools provided by Android to track the memory allocation of major application functions.