Performance optimization for rendering performance optimization

Source: Internet
Author: User
Tags memory usage stub xmlns
1 Knowledge Reserves

CPU:: Central processor, it integrates operation, buffering, control unit, including drawing function. The CPU handles objects as multidimensional graphics, textures (Bitmaps, drawables, and so on, all packaged together into a uniform texture).
GPU: A CPU-like processor specifically designed to handle graphics, to help speed up grid operations, and, of course, to have the appropriate cache data (such as caching already rasterized bitmap) mechanism.
OpenGL ES: A 3DAPI, cross-platform, fully functional 2D and 3D graphics API for handheld embedded devices, with a fixed rendering pipeline process.
Displaylist transforms an XML layout file into an object that the GPU can recognize and draw on Android. This is done with the help of Displaylist, Displaylist holds all the data information that will be given to the GPU to draw to the screen.
Grid: Is the Button,shape,path,string,bitmap and other components such as vector resources, into a pixel pixel pixels, displayed on the screen (Hardware: Image processor, GPU graphics processor), the process diagram is as follows:

Vertical Sync VSync: Let the graphics card's operation and display refresh rate consistent to stabilize the output picture quality. It tells the GPU to wait for the screen drawing to finish before loading a new frame. The following three images are what happens with GPU and hardware synchronization. ①refresh Rate: The number of times the screen is refreshed in one second, as determined by the hardware, such as 60Hz. ②frame Rate:gpu The number of frames for a second drawing operation, for example: 60fps. The normal process diagram is as follows:
2 rendering mechanism analysis 2.1 Rendering Pipeline

The rendering pipeline for the Android system is divided into two key components: CPU and GPU, which work together to draw pictures on the screen, each with a specific process defined by itself. We have to follow these specific rules of operation to achieve results.

  on the CPU side , the most common performance issues are: unnecessary and defunct layouts that must be measured, purged, and recreated in the view hierarchy . There are usually two reasons to cause this problem: one is to rebuild the display list too many times, and the other is to spend too much time on the view hierarchy and unnecessary repainting, for two reasons the CPU is overworked when updating the display list or other cache GPU resources.
  on the GPU side , the most common problem is what we're talking about: over-Drawing (Overdraw), which is often a waste of GPU processing time during pixel shading, when it's later shaded with other tools.

Before the CPU draws an image on the screen, it enters the specified set of instructions to the GPU, which is used by the GPU, mainly polygons and textures (pictures), which is the most commonly used API for Android's OpenGL ES. This means that when you draw a UI object on the screen, whether it's a button, a path, or a check box, you first need to calculate and convert to polygons and texture (polygons and textures) in the CPU, and then use OpenGL ES passes the computed polygons and texture to the GPU, and finally the GPU is rasterized. 2.2 Rendering process lines

UI object-–>CPU is processed as a multidimensional graphic, texture-–> is called by Opegl es interface gpu-–> GPU to rasterize the graph (Frame rate)-–> hardware clock (Refresh rate)-–> Vertical Sync-- > Project to the screen.

Image from: In-depth android rendering mechanism 2.3 render timeline

The Android system emits a vsync signal (1000ms/60=16.66ms) every 16ms, triggering the UI rendering, if each render is successful, so that you can achieve a smooth picture of the 60fps required, in order to achieve 60fps, This means that most of the operations that compute the rendering must be done within 16MS.
Normal:

Render time-out and calculate rendering times of more than 16ms. When the frame rendering time exceeds 16ms, the vertical synchronization mechanism will allow the display hardware to wait for the GPU to complete the raster rendering operation, which will allow this frame to stay more than 16ms or more. This creates a pause in the user's appearance.
when the GPU renders too slowly, some frames display the same screen content as the previous frame:
3 Rendering time-consuming three processes and optimization direction 3.1 Calculating the time-consuming

  Optimization direction : CPU optimization, from reducing processing view objects into polygons (polygons) and texture (textures), to measure, clear, and recreate unnecessary and ineffective layouts .
Any time the drawing content in the view changes, the creation of displaylist, rendering displaylist, and updating to the screen will be performed in a series of actions. The performance of this process depends on the complexity of your view, the state of the view, and the execution performance of the rendering pipeline. For example: When the size of the view changes, the displaylist is recreated and then rendered, and when the view shifts, the displaylist is not recreated, but the re-rendered operation is performed. When your view is too complex, and the operation is too complex, it will calculate the rendering time of more than 16ms, creating a lag problem.
Render time-consuming rendering tool-GPU rendering mode analysis. Each bar contains three parts: Blue represents the time the display list is plotted , red indicates the time required for OpenGL to render the display list , and yellow represents the time the CPU waits for GPU processing . There is a green line in the middle, representing 16ms, and you need to make sure that the total time spent on each frame is lower than the horizontal line, so that you can avoid the problem of stalling.
It also takes time for the 3.2 CPU to pass the computed polygons and texture to the GPU

  Optimization Direction : OpenGL ES API allows data to be stored and cached after uploading to the GPU. 3.3 over-painting when GPU is not rasterized

  optimization Direction : Try to avoid over drawing (overdraw)
The GPU drawing process, like the brush wall, a layer of the conduct, 16ms brush once. This creates a layer overlay, where useless layers are also drawn to the ground, creating unnecessary waste.

Over-drawing the view tool using the steps: Setup-developer options, debug GPU over-drawing, display GPU over-drawing. The legend shows over-rendering:

As over-drawing increases, the color of the marker will gradually deepen, for example, 1 time times over-drawn will be marked blue, twice times, 3 times times, 4 times times too much drawing follows the same pattern. 4 Rendering Optimization method to measure, clear, and recreate unnecessary and defunct layouts 4.1 Hierarchy Viewer Hierarchy Layout tool uses 4.1.1 Reduce unnecessary levels and skillfully use the Hierarchy Viewer tool

(1) Where is the Hierarchy viewer?

(2) How to use. A picture wins thousands of words (recommended for use in simulators)
4.1.2 can't show 3 circles what to do.

(1) Error, prompt as follows log:

[2016-11-20 15:59:49-viewserverdevice] Unable to debug device:nem_ul10-52f4c16425002867

(2) Workaround: Turn off developer mode and reopen.
4.1.3 can not connect to the real machine debugging what to do.

In the official Android document, there is a saying: For security reasons, the Hierarchy Viewer can only connect to Android-developed phones or emulators. Recommended method: Google big god Romainguy on GitHub project Viewserver, can be implemented with hierarchyviewer tools for viewing and debugging the application UI.
can be downloaded to import into the IDE, there is a Viewserver class, the class annotations are also annotated with the use of the introduction method has two kinds:

1 Add dependent
dependencies {
    Compile project (': Viewserver ')
}

//2 add Viewserver.java to Project

In baseactivity or the activity you want to debug, add a few lines of code in the following three methods:

public class Baseactivity extends Activity {public
    void OnCreate (Bundle savedinstancestate) {
        super.oncreate ( Savedinstancestate);
        Viewserver.get (This). AddWindow (this);
    }
    public void Onresume () {
        super.onresume ();
        Viewserver.get (This). Setfocusedwindow (this);
    }
    public void OnDestroy () {
        Super.ondestroy ();
        Viewserver.get (This). Removewindow (this);
    }
}
4.1.4 Focus on the following three circles

From left to right, it represents view: Measure, layout and draw performance, different colors represent different performance levels:
(1) Green: The rendered pipeline stage, this view renders faster than at least half of the other views.
(2) Yellow: Rendering speed is relatively slow 50%.
(3) Red: rendering speed is very slow. analysis of 4.1.5 measurement results

Red nodes represent a potential problem for slow application performance, and here are a few examples of how to analyze and interpret the cause of the red dot .
(1) If the root view in the view hierarchy, the messure stage is red, the layout stage is red, the draw stage is yellow, this is more common , because this node is the parent of all other views;
(2) If There are many sub-nodes in a view group, and the measurement stage is red, you need to observe the drawing of the child nodes ;
(3) If there are very few sub-nodes in the leaf node or ViewGroup , this may not be slow on the device, but it is necessary to point out why the node is red and can get additional information with Systrace or TraceView tools. ;
(4) If a leaf node in the view structure , there are 20 views is the red draw phase , this is problematic, you need to check the code inside the OnDraw method . 4.2 Optimizing layout Recommendations 4.2.1 Layout-level flattening

A tool to view the time-consuming situation and depth of the layout tree, the key to improving layout performance is to keep the layout hierarchy flat and avoid duplicate nesting layouts . Using linear layout LinearLayout causes the layout hierarchy to become darker, and if there is such a problem, use relative layout relativelayout instead of linearlayout, reducing the level of layout Because the Relativelayout version is better than the linearlayout.
For example, in the example below, there are 2 rows of views that show the same content, each of which is implemented in two different ways, with different hierarchies.
4.2.2 Does the outer parent container for each layout need?

A root layout that is not used is a root layout that has no background drawing or no size limit, so that the layout does not have any effect on the UI effect. We can reduce the level by merging the unused root layouts with merge tags, and delete the unused parent layout. Here is an example: when its layout code is as follows:

<?xml version= "1.0" encoding= "Utf-8"?> <linearlayout xmlns:android= "http://schemas.android.com/apk/res/ Android "Android:layout_width=" Match_parent "android:layout_height=" match_parent "android:orientation=" Vertica
        L "> <linearlayout android:layout_width=" match_parent "android:layout_height=" Wrap_content "
            android:orientation= "vertical" > <linearlayout android:layout_width= "match_parent"
                android:layout_height= "match_parent" android:orientation= "vertical" > <button Android:layout_width= "Wrap_content" android:layout_height= "Wrap_content" Android:onclick = "Startactivityb" android:text= "Start Activityb"/> <button android:layout_w
                Idth= "Wrap_content" android:layout_height= "wrap_content" android:onclick= "Startactivityb" android:text= "Start ACTivityb "/> </LinearLayout> </LinearLayout> </LinearLayout> 


Use the unused root layout to reduce the hierarchy by merging merge tags; remove the unused parent layout after:

<?xml version= "1.0" encoding= "Utf-8"?> <merge
xmlns:android= "http://schemas.android.com/apk/res/ Android "
    android:layout_width=" match_parent "
    android:layout_height=" match_parent "
    android:o rientation= "vertical" >
    <button
        android:layout_width= "wrap_content"
        android:layout_height= " Wrap_content "
        android:onclick=" startactivityb "
        android:text=" Start Activityb "/>
    <button
        Android:layout_width= "Wrap_content"
        android:layout_height= "wrap_content"
        android:onclick= " Startactivityb "
        android:text=" Start Activityb "/>
</merge>


  
  Merge tags are merged. The merge must be placed on the root node of the layout file; Merge is not a viewgroup, nor a view, and all properties set on the merge tag are not valid. If it is a merge tag, add the child elements directly to the merge label parent, which guarantees that no additional hierarchies are introduced. So:
(1) Merge can only be used as the root tag of the XML layout;
(2) When inflate a layout file that begins with < merge/>, you must specify a parent ViewGroup, and you must set Attachtoroot to True. Such as:

Layoutinflater.inflate (Xmlpullparser parser, ViewGroup root, Boolean attachtoroot)

(3) If the activity's layout file root node is framelayout, can be replaced with the merge label, so that after the execution of Setcontentview, a layer of framelayout nodes will be reduced;
(4) Custom View If you inherit LinearLayout, it is recommended that you set the layout file root node of your custom view to merge so that you have less nodes. 4.2.3 include layout reuse

In Android application development, the title bar is an essential element, most of the pages are used, and the layout is the same, the use of the include tag is extremely convenient. It is often important to note the following:

The Layout_* property of the include tag replaces the corresponding attribute of the root node of the include view.
the id attribute of the include tag replaces the root node ID of the include view, and if the Get root node ID view throws a null pointer
<?xml version= "1.0" encoding= "Utf-8"?> <linearlayout
xmlns:android= "http://schemas.android.com/apk/ Res/android "
    android:layout_width=" match_parent "
    android:layout_height=" match_parent "
    android:o rientation= "vertical"
    android:background= "#000000" >

    <include layout= "@layout/titlebar_layout" > </include>

    <textview
        android:layout_width= "match_parent"
        android:layout_height= "Match_ Parent "
        android:text=" This is the content area "
        android:gravity=" center "
        android:textsize=" 25SP "
        android: Textcolor= "#ffffff"/>
</LinearLayout>

Android layout optimization include with merge 4.2.4 viewstub label lazy loading less commonly used layouts

The biggest advantage of the viewstub tag is that it does not load when you need it, and it doesn't affect performance when the UI is initialized. A variety of infrequently used layouts like: progress bars, display error messages, etc. , you can use viewstub tags to reduce memory usage and speed up rendering.

<viewstub
        android:id= "@+id/stub"
        android:inflatedid= "@+id/subtree"
        android:layout= "@layout/my_ Sub_tree "//my_sub_tree.xml is lazy load view
        android:layout_width=" wrap_content "
        android:layout_height=" Wrap_ Content "/>  
Setvisibility can be called multiple times, but not recommended  
//If the referenced view has been reclaimed by the garbage collector, an exception is thrown, which is why setvisibility can be called multiple times, but it is not recommended for this reason
( viewstub) Findviewbyid (R.id.stub_import)). Setvisibility (view.visible);

The OR/  

////can only be called once, and the second call throws an exception "Viewstub must have a non-null viewgroup viewparent"
// Parent.removeviewinlayout (this) is invoked because Viewstub successfully executes the inflate method;
Remove itself from the parent node so Viewstub's inflate can only be called once
Mode 1, Get viewstub,  
viewstub liststub = (viewstub) Findviewbyid (r.id.stub);  
Liststub.setvisibility (view.visible);  
ListView COMMLV = Findviewbyid (R.ID.STUB_COMM_LV);  
if (liststub.getvisibility () = = view.visible) {  
    //already loaded, otherwise not loaded  
}  
Mode two  
View commlv2;//global variable

viewstub listStub2 = (viewstub) Findviewbyid (r.id.stub);  
if (commLv2 = = null) {  
    commLv2 = (ListView) liststub2.inflate ();  
} else {  
    //Viewstub already loaded  
}  

Android UI Layout Optimization viewstub: Use + source analysis 4.2.5 ListView does not use package content properties

Avoid the 3 circles in the ListView from reporting red, as far as possible without using the package content properties.
 <listview
      android:id= "@+id/listview"
      android:layout_width= "Match_parent"
      android: layout_height= "Match_parent"
      android:scrollbars= "vertical"/>
5 Rendering Optimization method 2--opengl es system optimization
Wait
6 Rendering Optimization method 3--avoid over-drawing (overdraw) 6.1 Remove unnecessary backgrounds and pictures


To begin the rendering of the pre-purge:

What to erase: unnecessary background:

The file of our main layout is already background white, so you can remove the
linearlayout
android:background= "@ of the ListView in the background//item layout Android:color/darker_gray "
//Relativelayout android:background= in the item layout
" @android: Color/white "
//
android:background= "@android: Color/white" for TextView with ID id_msg in the item layout

The rendered drawing after clearing:
6.2 Keep The activity's gray background, not over-drawn

Our activity requires the background color is gray, we do have to set in the layout of Gray, then note that the layout of our activity will eventually be added to the Decorview, this view will be in the background is not necessary, So we want to call Mdecor.setwindowbackground (drawable), then we can call GetWindow (). setbackgrounddrawable (NULL) in the activity. You can avoid over-drawing a layer .

Setcontentview (r.layout.activity_overdraw_01) after the OnCreate method of activity;
GetWindow (). setbackgrounddrawable (NULL);
Set the background color in layout colorprimary
<?xml version= "1.0" encoding= "Utf-8"?> <linearlayout xmlns:android
= "Http://schemas.android.com/apk/res/android"
    android:layout_width= "match_parent"
    android:layout_ height= "Match_parent"
    android:background= "@color/fragment_bg" android:orientation= "vertical"
    >
</LinearLayout>

6.3 Remove unnecessary background color or picture after ImageView loading

(1) Setting method
This background is more difficult to find, the main need to see adapter GetView code, the above code you will find, first set a background image for each icon (mainly when the icon is not shown when the time to display), and then set up an avatar. So it caused the overdraw, there is absolutely no need to draw the background of the avatar, all the modified code:

Droid droid = GetItem (position);
if (Droid.imageid ==-1) {
    holder.icon.setBackgroundColor (0x4400ff00);
    Holder.icon.setImageResource (color.transparent);
} else {
    holder.icon.setImageResource (Droid.imageid);
    Holder.icon.setBackgroundResource (color.transparent);
}

(2) Look at the last show GPU Overdraw vs. initial comparison
6.4 Optimizing the calculation of custom view 6.4.1 The situation of excessive drawing

(1) Often due to negligence caused a lot of unnecessary drawing, such as people look at the following chart. Multiple cards overlay, then if you are a card from left to right draw, the effect is certainly not a problem, but the superimposed area must be over-drawn. and material design is more likely to cause the above problems in the new style of interface designs. So what's the best way to improve it?

(2) The answer is: The Android Canvas object gives us a handy way to cliprect the overlay of the view and increase the CPU's computational capacity to optimize GPU rendering. 6.4.2 Source Demo

(1) Activity code

public class OverDrawActivity02 extends Appcompatactivity {
    @Override
    protected void onCreate (@Nullable Bundle Savedinstancestate) {
        super.oncreate (savedinstancestate);
        Setcontentview (New CardView (this));
    }
}

(2.1) Pre-CardView code not modified

/**
 * CardView */public
class CardView extends View {
    private bitmap[] mcards = new Bitmap[3];
    Private int[] Mimgid = new Int[]{r.drawable.alex, R.drawable.chris, r.drawable.claire};
    Public CardView (Context context) {
        super (context);
        Bitmap BM = NULL;
        for (int i = 0; i < mcards.length; i++) {
            BM = Bitmapfactory.decoderesource (Getresources (), mimgid[i]);
            Mcards[i] = Bitmap.createscaledbitmap (BM, n, +, false);
        }
        SetBackgroundColor (0XFF00FF00);
    }

    @Override
    protected void OnDraw (canvas canvas) {
        super.ondraw (canvas);
        Canvas.save ();
        Canvas.translate (+);
        for (Bitmap bitmap:mcards) {
            canvas.translate (0);
            Canvas.drawbitmap (bitmap, 0, 0, null);
        }
        Canvas.restore ();
    }
}

(2.2) Modified CardView code

/**
 * Analysis, except that the last one needs a complete drawing, the others only need to draw the parts, so we in the loop, I to n-1 have added Cliprect code.
 *
 /@Override protected void OnDraw (canvas canvas) {
     super.ondraw (canvas);
     Canvas.save ();
     Canvas.translate (+);
     for (int i = 0; i < mcards.length; i++) {
         canvas.translate (0);
         Canvas.save ();
         if (I < mcards.length-1) {
             canvas.cliprect (0, 0, +, mcards[i].getheight ());
         }
         Canvas.drawbitmap (Mcards[i], 0, 0, null);
         Canvas.restore ();
     }
     Canvas.restore ();
}
6.4.3 Final effect diagram

7 Summary

Performance optimization is not only a technology, but a thought, you have only heard it on the tall, but do not know that it is actually the details of the deep research and processing. Of course, there are times when you need to weigh the effects and performance on your own and choose according to your needs. Also,Android Device Monitor is a good thing, it's a performance optimization base, and the tools for performance optimization are basically there.
So in peacetime development process, develop good thinking habit is the first step:

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.