blob: 5d2cd89c05552b30aa55c41fdb2ee09e079a30aa [file] [log] [blame]
page.title=Analyzing UI Performance with Systrace
page.tags=systrace,speed
parent.title=Debugging
parent.link=index.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
<li><a href="#overview">Overview</a></li>
<li><a href="#generate">Generating a Trace</a></li>
<li><a href="#analysis">Analyzing a Trace</a>
<ol>
<li><a href="#frames">Inspecting Frames</a></li>
<li><a href="#alerts">Investigating Alerts</a></li>
</ol>
</li>
<li><a href="#app-trace">Tracing Application Code</a></li>
</ol>
<h2>See also</h2>
<ol>
<li><a href="{@docRoot}tools/help/systrace.html">Systrace</a></li>
</ol>
</div>
</div>
<p>While developing your application, you should check that user interactions are buttery smooth,
running at a consistent 60 frames per second. If something goes wrong, and a frame gets dropped, the
first step in fixing the problem is understanding what the system is doing.</p>
<p>The Systrace tool allows you to collect and inspect timing information across an entire Android
device, which is called a <em>trace</em>. It shows where time and CPU cycles are being spent,
displaying what each thread and process is doing at any given time. It also inpects the captured
tracing information to highlight problems that it observes, from list item recycling to rendering
content, and provide recommendations about how to fix them. This document explains how to navigate
the trace files produced by the tool, and use them to analyze the performance of an application's
user interface (UI).</p>
<h2 id="overview">Overview</h2>
<p>Systrace helps you analyze how the execution of your application fits into the many running
systems on an Android device. It puts together system and application thread execution on a common
timeline. In order to analyze your app with Systrace, you first collect a trace log of your app, and
the system activity. The generated trace allows you to view highly detailed, interactive reports
showing everything happening the system for the traced duration.</p>
<img src="{@docRoot}images/systrace/overview.png" alt="Systrace example overview" id="figure1" />
<p class="img-caption">
<strong>Figure 1.</strong> An example Systrace, showing 5 seconds of scrolling an app when it
is not performing well.
</p>
<p>Figure 1. shows a trace captured while scrolling an app that is not rendering smoothly. By
default, a zoomed out view of the traced duration is shown. The horizontal axis is time, and trace
events are grouped by process, and then by thread on the vertical axis.</p>
<p>The groupings are in the order Kernel, SurfaceFlinger (the android compositor process), followed
by apps, each labeled by package name. Each app process contains all of the tracing signals from
each thread it contains, including a hierarchy of high level tracing events based on the enabled
tracing categories.</p>
<h2 id="generate">Generating a Trace</h2>
<p>In order to create a trace of your application, you must perform a few setup steps. First, you
must have a device running Android 4.1 (API 16) or higher. Set up the device
for <a href="{@docRoot}tools/device.html#setting-up">debugging</a>, connect it to your development
system, and install your application. Some types of trace information, specifically disk activity
and kernel work queues, require that you have root access to the device. However, most Systrace log
data only requires that the device be enabled for developer debugging.</p>
<p>Systrace traces can be run either from
a <a href="{@docRoot}tools/help/systrace.html#options">command line</a> or from a
<a href="{@docRoot}tools/help/systrace.html#gui">graphical user interface</a>. This guide focuses on
using the command line options.</p>
<h3 id="running-4.3">Tracing on Android 4.3 and higher</h3>
<p>To run a trace on Android 4.3 and higher devices:</p>
<ol>
<li>Make sure the device is connected through a USB cable and is
<a href="{@docRoot}tools/device.html#setting-up">enabled for debugging</a>.</li>
<li>Run the trace with the options you want, for example:
<pre>
$ cd android-sdk/platform-tools/systrace
$ python systrace.py --time=10 -o mynewtrace.html sched gfx view wm
</pre>
</li>
<li>On the device, execute any user actions you want be included in the trace.</li>
</ol>
<p>For more information on the available options for running Systrace, see the
<a href="#options-4.3">Systrace</a> help page.</p>
<h3 id="running-4.2">Tracing on Android 4.2 and lower</h3>
<p>To use Systrace effectively with devices running Android 4.2 and lower,
you must configure the types of processes you want to trace before running a trace.
The tool can gather the following types of process information:</p>
<ul>
<li>General system processes such as graphics, audio and input processes (selected using trace
<a href="#tags">category tags</a>).</li>
<li>Low level system information such as CPU, kernel and disk activity (selected using
<a href="#options">options</a>).</li>
</ul>
<p>To set trace tags for Systrace using the command-line:</p>
<ol>
<li>Use the {@code --set-tags} option:
<pre>
$ cd android-sdk/platform-tools/systrace
$ python systrace.py --set-tags=gfx,view,wm
</pre>
</li>
<li>Stop and restart the {@code adb} shell to enable tracing of these processes.
<pre>
$ adb shell stop
$ adb shell start
</pre></li>
</ol>
<p>To set trace tags for Systrace using the device user interface:</p>
<ol>
<li>On the device connected for tracing, navigate to: <strong>Settings &gt;
Developer options &gt; Monitoring &gt; Enable traces</strong>.</li>
<li>Select the categories of processes to be traced and click <strong>OK</strong>.</li>
</ol>
<p class="note">
<strong>Note:</strong> The {@code adb} shell does not have to be stopped and restarted when
selecting trace tags using this method.
</p>
<p>After you have configured the category tags for your trace, you can start collecting
information for analysis.</p>
<p>To run a trace using the current trace tag settings:</p>
<ol>
<li>Make sure the device is connected through a USB cable and is
<a href="{@docRoot}tools/device.html#setting-up">enabled for debugging</a>.</li>
<li>Run the trace with the low-level system trace options and limits you want, for example:
<pre>
$ python systrace.py --cpu-freq --cpu-load --time=10 -o mytracefile.html
</pre>
</li>
<li>On the device, execute any user actions you want be included in the trace.</li>
</ol>
<p>For more information on the available options for running Systrace, see the
<a href="#options-pre-4.3">Systrace</a> help page.</p>
<h2 id="analysis">Analyzing a Trace</h2>
<p>After you have generated a trace, open the output html file using a web browser. This section
explains how to analyze and interpret the information that the tool produces to find and fix UI
performance problems.</p>
<h3 id="frames">Inspecting Frames</h3>
<p>Each app that is rendering frames shows a row of frame circles, which are typically colored
green. Circles that are colored yellow or red, exceeding the 16.6 millisecond run time limit
required to maintain a stable 60 frames per second. Zoom in using the 'w' key to see the frames of
your application, and look for long-running frames getting in the way of smoothness.</p>
<p class="note">
<strong>Note:</strong> Hit the '?' key, or the button in the top right for help navigating the
trace.
</p>
<img src="{@docRoot}images/systrace/frame-unselected.png" alt="Zoomed in view of a frame" id="figure2" />
<p class="img-caption">
<strong>Figure 2.</strong> Systrace display after zooming in on a long-running frame.
</p>
<p>Clicking on one such frame highlights it, focusing only on the work done by the system for that
frame. On devices running Android 5.0 (API level 21) or higher, this work is split between the UI
Thread and RenderThread. On prior versions, all work in creating a frame is done on the UI
Thread.</p>
<p>Click on individual components of the frame to see how long they took to run. Some events, such
as <em>performTraversals</em>, describe what the system is doing in that method when you select
it. Selecting a frame displays any alerts present in that frame.</p>
<h3 id="alerts">Investigating Alerts</h3>
<p>Systrace does automatic analysis of the events in the trace, and highlights many performance
problems as alerts, suggesting what to do next.</p>
<img src="{@docRoot}images/systrace/frame-selected.png" alt="Problematic frame selected" id="figure3" />
<p class="img-caption">
<strong>Figure 3.</strong> Selecting the problematic frame, an alert is shown identifying a problem.
</p>
<p>After you select a slow frame such as the one shown in Figure 3, an alert may be displayed. In
the case above, it calls out that the primary problem with the frame is too much work being done
inside {@link android.widget.ListView} recycling and rebinding. There are links to the relevant
events in the trace, which can be followed to explain more about what the system is doing during
this time.</p>
<p>If you see too much work being done on the UI thread, as in this case with this
{@link android.widget.ListView} work, you can
use <a href="{@docRoot}tools/debugging/debugging-tracing.html">Traceview</a>, the app code profiling
tool, to investigate exactly what is taking so much time.</p>
<p>Note that you can also find about every alert in the trace by clicking the <em>Alerts</em> tab to
the far right of the window. Doing so expands the Alerts panel, where you can see every alert that
the tool discovered in your trace, along with an occurrence count.</p>
<img src="{@docRoot}images/systrace/frame-selected-alert-tab.png" alt="Alert tab shown" id="figure4" />
<p class="img-caption">
<strong>Figure 4.</strong> Clicking the Alert button to the right reveals the alert tab.
</p>
<p>The Alerts panel helps you see which problems occur in the trace, and how often they contribute
to jank. Think of the alerts panel as a list of bugs to be fixed, often a tiny change or improvement
in one area can eliminate an entire class of alerts from your application!</p>
<h2 id="app-trace">Tracing Application Code</h2>
<p>The tracing signals defined by the framework do not have visibility into everything your
application is doing, so you may want to add your own. In Android 4.3 (API level 18) and higher, you
can use the methods of the {@link android.os.Trace} class to add signals to your code. This
technique can help you see what work your application's threads are doing at any given time. Tracing
begin and end events do add overhead while a trace is being captured, a few microseconds each, but
sprinkling in a few per frame, or per worker thread task can go a long way to adding context to a
trace of your app.</p>
<p>The following code example shows how to use the {@link android.os.Trace} class to track
execution of an application method, including two nested code blocks within that method.</p>
<pre>
public void ProcessPeople() {
Trace.beginSection("ProcessPeople");
try {
Trace.beginSection("Processing Jane");
try {
// code for Jane task...
} finally {
Trace.endSection(); // ends "Processing Jane"
}
Trace.beginSection("Processing John");
try {
// code for John task...
} finally {
Trace.endSection(); // ends "Processing John"
}
} finally {
Trace.endSection(); // ends "ProcessPeople"
}
}
</pre>
<!-- todo: move these two Notes to the android.os.Trace class -->
<p class="note">
<strong>Note:</strong> When you nest trace calls within each other, the
{@link android.os.Trace#endSection} method ends the most recently called
{@link android.os.Trace#beginSection} method. This means that a trace started within another
trace cannot extend beyond the end of the enclosing trace, so make sure your beginning and
ending method calls are properly matched to measure your applications processing.
</p>
<p class="note">
<strong>Note:</strong> Traces must begin and end on the same thread. Do not call
{@link android.os.Trace#beginSection} on one thread of execution and then attempt to end the
trace with a call to {@link android.os.Trace#endSection} on another thread.
</p>
<p>When using application-level tracing with Systrace, you must specify the package name of your
application in the user interface or specify the {@code -a} or {@code --app=} options on the
command line. For more information, see the
<a href="{@docRoot}tools/help/systrace.html">Systrace usage guide</a>.</p>
<p>You should enable app level tracing when profiling your app, even if you have not added signals
yourself. Library code can include very useful tracing signals when you enable application-level
tracing. The {@link android.support.v7.widget.RecyclerView} class is a great example of this,
providing information about several important stages of work it executes.</p>