Before you begin to work with performance effectively, we recommend you make yourself familiar with key performance metrics. By understanding what metrics you should look at, you will make inspecting, improving and monitoring performance easier.
This MAD Skills article on important performance metrics will introduce you to startup and frame rate metrics and bring in important data points for the rest of this series on performance. App startup and creating a smooth user experience have shown to have a lasting impact on user satisfaction and applications’ individual business metrics, which is why we have chosen these areas as focal points for this article.
Later in this series we have tools and libraries lined up to make it easier for you to inspect, improve, and monitor performance.
Make sure to leave a comment here, on YouTube or using #MADPerfQA on Twitter so we can get back and even answer in our live streamed Q&A session on Sept 1st.
You can watch the accompanying video to this article here.
Application startups are the first point of interaction with your user. Making a lasting and positive first impression is even more important at scale. So your goal is to make the app startup as fast, seamless and smooth as possible.
App startup can be measured in three phases: Cold, warm and hot start.
The startup phase is determined by the current state of your app.
A cold start begins when the application’s process is created. This is what users experience when they install your app and then launch it for the first time, launch the app after restarting their device or restart the app after the system has completely stopped it for one reason or another.
During a cold start,
Application.onCreate() is called. Everything your app needs to get started is loaded from disk. When a cold start begins, memory caches are empty as well. Cold starts are the slowest startup type, because they start at process creation and end at the same time a hot start finishes. To experience a cold start of your app, force-close it and then open it again from the launcher.
Cold starts should be faster than 500 milliseconds.
When a cold start takes longer than 500 milliseconds, your users are going to notice and might get increasingly impatient and might decide to move away from your app. So keeping cold starts as fast as possible is extremely important.
A warm start is measured from the point when
Activity.onCreate() is called, just before your view hierarchy is inflated.
At this point, some resources are already inflated and memory caches warmed up.
Warm starts usually take place when you open an app after the activity was destroyed, but the app’s process is still running.
This could happen if an app has been running in the background for a while, but not long enough for the system to kill the entire process. Also, whenever an orientation change forces the activity to be destroyed and re-created, that’s a warm start.
The final and shortest app startup type is called hot start. During a hot start, an app that is running, such an activity that was paused, becomes visible to the user and enters the started state.
Here the first frame is ready to be drawn and
Activity.onStart() is called. A hot start can happen when you’re switching back and forth between apps.
Due to the nature of startup types, a cold start takes the most time. Warm and hot starts will be shorter.
All three startup types, cold, warm and hot, are measured from their corresponding starting point to at least one of two end states.
Time to Initial Display
The default app startup end state is called Time to Initial Display. Or TTID for short. It is automatically reported when the first frame of your application is ready to be drawn.
You can also see TTID by opening logcat and looking for the
ActivityTaskManager tag with value
Displayed. It will tell you how much time it took to display a specific activity. Because this is reported automatically, there’s nothing for you to configure. Every app is reporting this by default.
Time to Full Display
While time to initial display is reported automatically, the next state can be customized. It is called time to full display, or TTFD. Time to full display is an optional metric that Android can use to further optimize your app’s startup time. It is also used when running startup benchmarks on your app.
TTFD is also visible in logcat with the
ActivityTaskManager tag. Look for
ActivityTaskManager: Fully drawn.
You should report time to full display when everything is drawn on screen, and the data required for the user to interact with the app is available.
The API to use is Activity’s reportFullyDrawn()
reportFullyDrawn is not tied to an Activity lifecycle method and you must pick the right time to call the API that makes sense for your app.
And while it’s important to call the method around the time your app is ready to be used, being absolutely precise on a frame level is not required.
The Now in Android sample app is considered to be fully drawn when both the interests and feed have been loaded.
Once these two states are met, we call
reportFullyDrawn when the current local view is ready to be drawn. You can check out the code in more detail on GitHub.
Making sure you don’t drop frames is very important for a smooth user experience. Most frames aren’t dropped in a static state but when the user is scrolling or you’re otherwise animating content. If an app is doing too much work on the main thread to meet the frame timing window, slow and frozen frames are the result.
We call this behavior Jank. Jank can be extremely frustrating so it’s important to know how to avoid it.
The screen can be drawn many times per second. The amount of re-draws per second is called frame rate.
Historically, Android devices came with a refresh rate of 60 frames per second. That gives your app 1/60th of a second to perform work on the main thread before a frame will be delayed or eventually has to be dropped. More recently, the frame rates have increased to 90 and even 120 frames per second.
And devices can also switch between different frame rates depending on a user’s choice, the developer’s decision, or even the device’s power or thermal state.
Within our Modern Android Development guides, we recommend you optimize for a frame rate of at least 90 frames per second. This means all the work in between frames has to fit in a window of less than 11.1 milliseconds. And that’s very, very little time.
A great way to achieve a high frame rate is to keep as much work as possible off the main thread.
In the next article we’ll introduce you to inspecting performance issues in detail.
Also, make sure to check out our full MAD Skills series on performance debugging to get an edge on how you can inspect what’s going on in your code.
Go and check out our improved developer documentation, which we have been updating with MAD guidance.
To get more hands on, check out the samples on GitHub.
Also, make sure to ask your questions in the video comments or on Twitter, using #MADPerfQA to get answers directly from the Engineers working on Android Performance.