[MUSIC PLAYING]
YI YANG: Hello, everyone.
My name's Yi.
I'm a software engineer on the Android Studio Team.
I'll be talking about how to troubleshoot performance
issues with Android Studio using a tool called System Trace.
First, I'm going to give you a quick overview of what
Android System Trace is.
Then, I'll go over what the tool looks like in Android Studio,
followed by a demo using the tool to de-investigate
a performance issue.
Your first reaction to our app being slow
is to investigate your app's code.
But that's not everything at play while it's executing.
First of all, there's the Android framework.
Then, there's the Linux kernel, and finally,
the mobile phone hardware.
System Trace helps developers like you
get the full picture of their app's runtime performance
by capturing performance data from all four layers.
From the hardware layer--
data like CPU frequency and CPU core scheduling.
From the kernel layer, thread state information, RSS memory
counters, and more.
From the Android framework layer,
events from activity manager, the graphics pipeline,
and other aspects of the framework.
You can optionally define custom events
to instrument your app code to tie app functionality
with the rest of all the data.
So in a nutshell, System Trace is a tool
that allows you to inspect how your app interacts
with system resources.
While you can use System Trace from the command line,
Android Studio CPU Profiler started
supporting System Tracing 3.2.
And we've been making improvements since then.
In 4.0, we revamped the System Trace UI
based on your feedback.
For instance, before 4.0, you can only
see trace events from one thread at a time, so we changed that.
We continue to polish it in 4.1.
This is what it looks like now.
On the top left corner where you can see a line chart of the app
CP usage, there's a timeline for the trace duration.
By selecting a range, you can zoom in and change
what's displayed below.
The main section of the trace UI shows data
from the selected range above and includes multiple sections.
Here, I just want to highlight the thread section.
As you can see, now you'll be able to view trace events
from all threads at once, allowing you to identify
busy threads from a glance.
Then, on the right-hand side, we added a new analysis panel
by default, a performance analysis on all threads,
as shown in the screenshot.
But once you have select something
on the left-hand side, the content will change.
There are different tabs in this panel, namely top down tree,
flame chart, and bottom up tree.
In Android Studio 4.1, we added a new Summary tab
to show you additional useful data.
OK, now it's time for a demo.
I'm going to first show you how to capture a System Trace.
Then, I'll walk you through the new UI
while I investigate a UI performance issue also known
as jank.
Here, I am running a sample app called
IOSched, the official app for showing Google IO and Android
devs on my schedules.
The project is open source.
And the link will be included in the video description.
For the purpose of this demo, I had planted
a performance bug in the app.
When navigating from the conference session list
to the session detail view, there is noticeable UI jank.
Let's see if we can find out what's
causing it using System Trace in Android Studio.
Here, I'm running Android Studio 4.1 beta three.
While the new System Trace UI is already available in 4.0,
it received some UI improvements in 4.1.
So I highly encourage you to try it out.
To capture a System Trace, we first need to start profilers.
Let's click into the CPU profiler.
In the recording panel, make sure we
select the Trace System Calls option
and click the Record button.
Then in the app, let me type on an item in the session list
to load the session details.
Then we go back to Android Studio and click Stop.
By the way, we've made some performance improvements when
it comes to parsing the trace.
It should now consume much less memory.
OK, now, we have the new trace UI in front of us.
The timeline here shows the duration
of the trace, which is about 10 seconds.
The very first thing we want to do is locate on this timeline
when the jank happened.
Usually the interaction section is a good place to start.
This dot here indicates a touch event,
which is when we tapped on the session item.
Then, in the lifecycle track, we have an event
showing where the main activity transitioned
from schedule fragment to session detail fragment.
So the jank we're investigating must
have happened between the touch event and the fragment
transition.
Now we can use the range selector
on the top to quickly zoom in and then
use WSD keyboard shortcut to center the area of interest.
Another way to zoom in is box selection-- one
of the UI improvements we made in Android Studio 4.1.
By just dragging a box around the area
and press the Zoom to Selection button or keyboard shortcut m,
we can precisely center the view to the area of interest.
Since we're investigating UI performance,
the display section might be helpful to us.
This section shows us data related to the Android graphics
pipeline.
On the first track, we have frames data.
This chart shows exactly how long
it takes to render each frame.
For smooth UI rendering, we want to aim
for 60 frames per second, which translates
to 16.7 millisecond per frame.
This tool colors frames longer than that threshold
red to help you easily locate long frames.
The next track added in Android Studio 4.1
is called SurfaceFlinger.
SurfaceFlinger is a process running in the background
on Android operating system.
It is responsible for processing buffers and sending them
to the display.
SurfaceFlinger only wakes up to accept buffers between display
refreshes to minimize memory usage and avoid screen tearing.
So having these events on the timeline
will help you discover potential UI-rendering bottlenecks
in your app.
The third track, also added in 4.1, is called VSync.
VSync is a synchronization signal
and synchronizes your app, SurfaceFlinger,
and the hardware refresh cycles so that users
don't see screen stuttering.
In a perfect world, you want your app
to render a frame before each VSync
to ensure smooth graphics.
Here, we can see these long frames missed several VSyncs.
And we are going to dig deeper.
By the way, there's actually more graphics data
than what's shown here.
We have a tool that specializes in graphics profiling.
And it even exposes DPU data.
It's called Android Graphics Inspector,
and is currently in developer preview.
I'll include a link in the video description for those
interested.
So I have several slow frames here.
To find out more, let's move on to the thread section.
By the way, you can reorganize sections
by moving them up or down or even
collapse them to hide individual sections.
As I said earlier, the new UI shows all thread activities
at once, making it easier to find the busy threads.
By default, they are sorted by the number
of events inside each thread.
But you can always drag and drop to reorder them
however you like.
Within each thread, there are two parts.
The top part shows thread states at any given time,
whether it's running or sleeping.
This is useful for debugging multi-threaded issues.
The bottom part shows all trace events in a tree-like graph.
By default, you get a trace event
from the Android framework layer already instrumented
by the team behind the Android OS.
You may also see custom events if you [INAUDIBLE]
your app's code using the Android tracing API, which
I'll show you in a second.
Here, let's dig deeper into this long frame.
Something stood out.
This res/drawable/android_banner.png
event indicates an image was being loaded during this frame.
It took about 50ish milliseconds, which
contributed to the slow frame.
This is actually the bug I had planted in the code.
I replaced a vector image with a 4,000-by-1,000 PNG image.
This would have been hard to detect by just
looking at your app code.
However, System Trace exposes instrumented events
from the framework layer, giving us data on how long
loading a large image takes.
There's something else I want to explore.
Between these two frames, there's a large gap.
Let's zoom in to see what's going on.
Here, we can see a couple of events called Inflate.
Inflate is a trace event for constructing a view hierarchy
from preprocessed xml via layout inflator.
This includes constructing all of the view
objects in the hierarchy and applying styled attributes.
This event is actually very common during UI
initialization.
In fact, we can select this event
to see all of their occurrences in the analysis panel.
Notice the panel changes its content
to reflect the currently selected
event instead of all threads.
In Android Studio 4.1, we added a new Summary tab
to show you a high-level summary of your select object.
For instance, when we select a trace event,
the Summary tab shows all occurrences of that event.
In addition to basic statistics, you
can find and navigate other instances of this event
in this table.
I also want to mention that charts,
like the top down tree, now scope
data to the selected event, making it easier to see data
you are interested in.
So I want to make sense of these inflate events.
I know session detail fragment does a lot of view inflation.
But what I want to do is correlate my [INAUDIBLE]
with these inflate events from System Trace.
To do that, I can add custom events
with the Android Tracing API.
The API provides two methods--
begin section and end section.
Here, I have a call to inflate speaker_shared_enter.
So let me wrap that with the tracing API.
The stream parameter here for beginning section
is the name that is going to show up in the trace UI.
OK, there are more inflate calls in this method.
So let me add more trace API calls.
Now, I can run profiler again and take another System Trace.
OK, similarly, I want to locate the area of interest here.
And if we zoom into this gap, you
can see now we have three new events which are the three
custom events I added--
speaker_shared_enter, app_team_detail, and
session_detail_menu.
With these customer events, now I
can correlate what my code is doing with this instrumentation
code from the Android framework.
In fact, this session_detail_menu event
could be another source of UI jank.
Not all of these menu items are visible.
But they are taking time to inflate the layout.
If we look at the top-down tree view,
we can get an aggregated view of the exact timing
of these trace events.
We can probably optimize in some of these.
There's one more thing I want to show.
I know some of you are concerned about your app startup
performance.
You can actually take System Trace during app startup.
To do that, just go to Run Configurations,
switch to the profiling app, and check this checkbox--
start this recording on startup.
Here, you can select the type of recording you want to take.
In addition to System Trace, you can also
record sample Java methods.
Then, the next time you profile your app,
it automatically starts System Trace on startup
so you don't miss anything during app startup.
Hopefully this demo can help you become
comfortable with using System Trace and Android Studio.
I know troubleshooting performance issues
is a difficult task.
So I hope these tools can make your lives a bit easier.
Here's a quick summary of what we talked about today.
System Trace helps you investigate performance issues
by showing you how your app interacts with system
resources, use customer events to correlate your app's code
with system events, and easily visualize them
in our trace report.
With Android Studio, you can iterate this process faster.
Finally, try out the latest Android Studio beta
and send us your feedback.
We really value your input and will improve our tools
based on your feedback.
Thank you.
[MUSIC PLAYING]