Android Performance Optimization Series – 01 Teach you step by step how to use systrace

1. Overview

Performance optimization is an important knowledge in Android and an important basis for measuring the level of an Android engineer. Many people may know simple performance optimization. For example, many people must know the following methods to optimize UI rendering:

  1. Use “Settings –> Developer Options –> Debugging GPU overdrawing” to distinguish whether there is overdrawing based on the different colors displayed on the screen, so as to check the xml file of the interface, remove unnecessary background, and eliminate overdrawing.

  2. View the layout hierarchy through Layout Inspector to check whether there are multiple levels of useless nesting (since Hierarchy Viewer has been deprecated, if you use Android Studio 3.1 and newer, it will be more convenient to use Layout Inspector to view the layout)

  3. Use ViewStub & amp; merge tags in xml to optimize layout hierarchy

The above points are of course important, but to some extent, the above methods are no longer enough, and we need to use other methods to optimize performance.

As the saying goes, if you want to do your job well, you must first sharpen your tools. Using a good tool can certainly help us get twice the result with half the effort. Due to the severe runtime overhead of TraceView, many data measured by TraceView have large deviations, so Google now Strongly recommend systrace, systrace is a very powerful performance analysis tool.

Systrace can collect and analyze the time information of all processes when the device is running at the system level. It collects information from the Android kernel, such as CPU scheduling, disk activity and app threads, and then generates an html file as shown in the figure below. It should be noted that the generated trace.html file must be opened with the Chrome browser before it can be browsed and used normally.

Image source: systrace. As shown in the picture above, each small circle in the ‘Frames’ line represents each frame, and different colors are used to represent normal rendering. If a certain small circle is represented by yellow/red, it indicates that this frame There may be a problem with the rendering of

Okay, let’s take a look at how to use the systrace tool

2. How to use

I use a Mac computer, so the following operations are performed on a Mac, and they should be similar on a Windows system.

2.1 Preparation

Before using systrace, you need to do the following preparations

  1. Newer Android SDK Tools

  2. Requires the cooperation of the PC side. Python is installed on the PC side and configured in the system environment variables.

  3. The device for debugging needs to be 4.3 (API Level 18) or above. The higher the system, the more information can be collected, which is more conducive to analysis. The application for analysis needs to be a debug package.

  4. The Android device and PC are successfully connected via USB and are in a debuggable state.

At this point, the preparation work has been completed

2.2 Use

2.2.1 How to use

Enter the /Android/sdk/platform-tools/systrace/ directory through Terminal

At this time, operate the application on the device to bring the application into a state to be debugged. For example, if you need to debug a certain page RecyclerView, enter the page.

Then run the following command in Terminal, where [options] [categories] are all parameters that need to be entered.

./systrace.py [options] [categories]

For example, execute the following command, where -o mynewtrace.html -t 10 belongs to the [options] parameter, sched freq idle am wm gfx view binder_driver hal dalvik camera input res belongs to the [categories] parameter

./systrace.py -o mynewtrace.html -t 10 sched freq idle am wm gfx view binder_driver hal dalvik camera input res

After running for 10 seconds, the recorded device activity will be generated into a file named mynewtrace.html.

2.2.2 Parameter Description

So what parameters do [options] and [categories] include?

[options] The parameters are fixed, and commonly used ones include the following

options Abbreviation Meaning
-o None Specifies the output file, such as: -o mynewtrace.html. If this parameter is not specified, the default name of the file is trace.html
–time= -t Specify the duration of systrace, such as -t 10, which means recording for 10 seconds. The unit of is s seconds. If this parameter is not specified, systrace will end when the Enter key Enter is pressed
–buf-size= -b The buffer of the specified systrace is N kb. Specify the total capacity of data collected during the systrace process
–app= -a Specify a specific application, such as: -a com.lijiankun24.shadowlayout. If Trace.beginSection("tag") and Trace.endSection are used in this application, these tags will not take effect by default unless you pass this The command specifies the application, and only the information about the method marked by the tag will be recorded in the html file output by systrace

Before introducing the [categories] parameter, let’s introduce two useful instructions of systrace

Global options Abbreviation Meaning
–help -h View help information
–list-categories – l Because different devices have different Android system versions, the supported [categories] parameters are also different. You can use this command to see which [categories] parameters are supported by the connected device

For example, the Android system of my device is Android 7.1.2. After running the following command, you can get the [categories] parameter information as shown in the figure below.

./systrace -l

The above [categories] parameters indicate which modules this device supports that can be recorded. The following modules are commonly used.

categories Full name Meaning
sched CPU Scheduling CPU scheduling information, you can see what threads are executed by each core of the CPU at a specific point in time
gfx Graphics Graphics rendering system, including SurfaceFlinger, VSync, Texture, RenderThread information
input Input Input event system, records keyboard input, touch and other event information
view View System View view system, common View onMeasure, onLayout, onDraw are all recorded in this system
wm Window Manager WindowManager’s calling information is recorded in this module
am Activity Manager ActivityManager’s calling information Recorded in this module
dalvik Dalvik VM Virtual machine related information, such as GC garbage collection information

Generating the trace.html file is probably like this, it is not complicated. Here are some shortcut keys for viewing this html file. Through the following common shortcut keys, you can easily view the html file.

Shortcut keys Meaning
W Zoom in timeline
S Zoom in timeline
A Move the timeline left
D Move the timeline right
Right Arrow Select the next event on the selected timeline
Left Arrow Select the previous event on the selected timeline

3. Analysis trace.html

3.1 Simple analysis of trace.html file

How do we analyze the generated trace.html file?

As shown in the figure below, it is an enlarged partial view of trace.html. We all know the concept of 60 fps in the Android system, that is, 60 frames will be rendered in 1 second, and it takes 16.6 ms to render one frame. Each frame is framed in red in the picture below. If the rendering is completed within 16.6 ms, then The frame is green, if it takes more than 16.6 ms to render, it will appear yellow or red

Image source systrace

In the picture above, after selecting the problematic yellow frame, you need to pay attention to two parts, as shown below

  1. In the first red box, the highlighted part is which methods are called in this frame in the UI thread and RenderThread thread.

  2. The second red box displays some information, including the very useful reason for the frame problem (Alert & Description). These are existing problems and optimization suggestions given by the system.

If we select the Alerts tab in the upper right corner in the picture above, the information shown in the picture below will appear, which tells us the frequency of the problem during this period, such as the picture below : Inefficient ListView recycling/rebinding appears 55 times in total.

You can think of the Alerts tab as a list of bugs that need to be dealt with. The problems in this list all cause problems to our frame rendering to varying degrees. Sometimes it may be just a few lines of code with minor changes and optimizations, but it can solve many of our problems.

3.2 Add Trace information to your application

By default, systrace can only record and collect system-level information, such as WindowManager, ActivityManager, and Dalvik and other modules. Is there any way to also record and collect itself? What about some information in the application?

Android provides such an API. This class is the Trace class. It is not difficult to use the Trace class to record information in your own application. As shown below, there are the following Points need attention

  1. Trace.beginSection(String sectionName) and Trace.endSection() need to appear in pairs to ensure that each Trace.beginSection(String sectionName) There will be corresponding Trace.endSection(). It is recommended to use try {…} finally {…}

  2. If there are multiple Trace.beginSection(String sectionName) before Trace.endSection(), Trace.endSection() will match the one closest to it An unmatched Trace.beginSection(String sectionName)

  3. Trace.beginSection(String sectionName) and Trace.endSection() need to be in the same thread

public class CardViewListActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Trace.beginSection("CardViewListActivity_onCreate");
        try {
            setContentView(R.layout.activity_card_view_list);
            RecyclerView recyclerView = findViewById(R.id.rv_card_view);
            recyclerView.setLayoutManager(new LinearLayoutManager(CardViewListActivity.this));
            recyclerView.setAdapter(new CardViewListAdapter());
        } finally {
            Trace.endSection();
        }
    }

    private static class CardViewListAdapter extends RecyclerView.Adapter<CardViewHolder> {

        @NonNull
        @Override
        public CardViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            Trace.beginSection("CardViewListAdapter_onCreateViewHolder");
            CardViewHolder viewHolder;
            try {
                View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_card_view_list, null);
                Trace.beginSection("CardViewListAdapter_onCreateViewHolder_newHolder");
                try {
                    viewHolder = new CardViewHolder(view);
                } finally {
                    Trace.endSection();
                }
            } finally {
                Trace.endSection();
            }
            return viewHolder;
        }

        …
    }

    …

}

After adding the above code to your own application code, it is not over. There is another very important point. When executing the systrace command, you need to specify the application package name through -a , so that it will be recorded. , collect the trace information added in your application, as shown below:

./systrace.py -t 10 -o mytrace.html -a com.lijiankun24.shadowlayout sched freq idle am wm gfx view binder_driver hal dalvik camera input res

In the generated trace.html file, you can find the sectionName by searching in the upper right corner, and then you can find the record information of the Trace.

3.3 Brief analysis of principles

In fact, the idea of systrace is very simple, which is to log in some critical paths. Through the start and end of the log, you can get the execution time information of a method, and then collect these logs to get the running time information of the critical path, and then Obtain operational performance information of the entire system.

Log through different methods or classes in Android applications, Android Framework and native layers

3.3.1 Android Framework
import android.os.Trace;
Trace.traceBegin(long traceTag, String methodName)
Trace.traceEnd(long traceTag)

For example, the internal class H.handleMessage(Message msg) method in ActivityThread is as follows

In the Android Framework, logging is done through the Trace.traceBegin(long traceTag, String methodName) method. The passed in traceTag is a constant class in the Trace class, as shown below

In fact, the Trace constant value here is the same as the [categories] value passed in when we execute ./systrace [options] [categories] corresponding

3.3.2 Android Applications

The corresponding traceTag name is TRACE_TAG_APP. When running with the systrace.py command, you need to specify the package name of the application through -a before you can collect buried trace tags. tag

import android.os.Trace;
Trace.beginSection(String sectionName)
Trace.EndSection()

The source code of the Trace class is as follows, you can see traceBegin(long traceTag, String methodName), traceEnd(long traceTag), beginSection(String sectionName) ), endSection() finally called the native methods nativeTraceBegin(long tag, String name) and nativeTraceEnd(long tag)

public final class Trace {

    @FastNative
    private static native void nativeTraceBegin(long tag, String name);
    @FastNative
    private static native void nativeTraceEnd(long tag);

    private Trace() {
    }

    ...

    public static void traceBegin(long traceTag, String methodName) {
        if (isTagEnabled(traceTag)) {
            nativeTraceBegin(traceTag, methodName);
        }
    }

    public static void traceEnd(long traceTag) {
        if (isTagEnabled(traceTag)) {
            nativeTraceEnd(traceTag);
        }
    }

    ...

    public static void beginSection(String sectionName) {
        if (isTagEnabled(TRACE_TAG_APP)) {
            if (sectionName.length() > MAX_SECTION_NAME_LEN) {
                throw new IllegalArgumentException("sectionName is too long");
            }
            nativeTraceBegin(TRACE_TAG_APP, sectionName);
        }
    }

    public static void endSection() {
        if (isTagEnabled(TRACE_TAG_APP)) {
            nativeTraceEnd(TRACE_TAG_APP);
        }
    }
}
3.3.3 native layer

In fact, systrace is essentially a package of other tools, including atrace on the PC side and ftrace on the device side. ftrace is the main tracing mechanism in the Linux kernel. . systrace uses atrace to start tracing, then reads the cache of ftrace and re-converts it into HTML format

#include<utils/Trace.h>
ATRACE_CALL();

The basic analysis methods and principles of systrace are introduced here. More in-depth analysis methods and principles will be updated in subsequent series, so stay tuned.

4. Reference

https://developer.android.com/studio/command-line/systrace

http://gityuan.com/2016/01/17/systrace/

Use Systrace to analyze UI performance – Jianshu