Networks Business Online Việt Nam & International VH2

App startup time | Android Developers

Đăng ngày 07 October, 2022 bởi admin
Users expect apps to be responsive and fast to load. An app with a slow start time doesn’t meet this expectation, and can be disappointing to users. This sort of poor experience may cause a user to rate your app poorly on the Play store, or even abandon your app altogether .
This document provides information to help you optimize your app’s launch time. It begins by explaining the internals of the launch process. Next, it discusses how to profile startup performance. Last, it describes some common start-time issues, and gives some hints on how to address them .

Understand the different app startup states

App launch can take place in one of three states, each affecting how long it takes for your app to become visible to the user : cold start, warm start, or hot start. In a cold start, your app starts from scratch. In the other states, the system needs to bring the running app from the background to the foreground. We recommend that you always optimize based on an assumption of a cold start. Doing so can improve the performance of warm and hot starts, as well .

To optimize your app for fast startup, it’s useful to understand what’s
happening at the system and app levels, and how they interact, in each of
these states.

Cold start

A cold start refers to an app’s starting from scratch : the system’s process has not, until this start, created the app’s process. Cold starts happen in cases such as your app’s being launched for the first time since the device booted, or since the system killed the app. This type of start presents the greatest challenge in terms of minimizing startup time, because the system and app have more work to do than in the other launch states .
At the beginning of a cold start, the system has three tasks. Thes e tasks are :

  1. Loading and launching the app.
  2. Displaying a blank starting window for the app immediately after launch.
  3. Create the app process.

As soon as the system creates the app process, the app process is responsible for the next stages :

  1. Creating the app object.
  2. Launching the main thread.
  3. Creating the main activity.
  4. Inflating views.
  5. Laying out the screen.
  6. Performing the initial draw.

Once the app process has completed the first draw, the system process swaps out the currently displayed background window, replacing it with the main activity. At this point, the user can start using the app .
Figure 1 shows how the system and app processes hand off work between each other .

Figure 1: A visual representation of the important parts of
a cold application launch.

Performance issues can arise during creation of the app and creation of the activity .

Application creation

When your application launches, the blank starting window remains on the màn hình hiển thị until the system finishes drawing the app for the first time. At that point, the system process swaps out the starting window for your app, allowing the user to start interacting with the app .

If you’ve overridden Application.onCreate()
in your own app, the system invokes the onCreate() method on your
app object. Afterwards, the app spawns the main thread, also known as the UI
thread, and tasks it with creating your main activity.

From this point, system – and app-level processes proceed in accordance with the app lifecycle stages .

Activity creation

After the app process creates your activity, the activity performs the following operations :

  1. Initializes values.
  2. Calls constructors.
  3. Calls the callback method, such as
    Activity.onCreate(),
    appropriate to the current lifecycle state of the activity.

Typically, the onCreate()
method has the greatest impact on load time, because it performs the work with
the highest overhead: loading and inflating views, and initializing the objects
needed for the activity to run.

Warm start

A warm start encompasses some subset of the operations that take place during a cold start ; at the same time, it represents more overhead than a hot start. There are many potential states that could be considered warm starts. For instance :

  • The user backs out of your app, but then re-launches it. The process may have
    continued to run, but the app must recreate the activity from scratch via a call
    to onCreate().

  • The system evicts your app from memory, and then the user re-launches it. The
    process and the activity need to be restarted, but the task can benefit somewhat
    from the saved instance state bundle passed into onCreate().

Hot start

A hot start of your application is much simpler and lower-overhead than a cold start. In a hot start, all the system does is bring your activity to the foreground. If all of your application’s activities are still resident in memory, then the app can avoid having to repeat object initialization, layout inflation, and rendering .

However, if some memory has been purged in response to memory trimming events,
such as onTrimMemory()
then those objects will need to be recreated in response to the hot start event.

A hot start displays the same on-screen behavior as a cold start scenario :
The system process displays a blank màn hình hiển thị until the app has finished rendering the activity .


Figure 2: This diagram displays the various startup states
and their respective processes, with each state beginning from the first frame
drawn.

Using metrics to detect and diagnose problems

In order to properly diagnose start time performance, you can track metrics that show how long it takes your application to start. Android provides several means of letting you know that your app has a problem, and to help you diagnose it. Android vitals can alert you that the problem is occurring, and diagnostic tools can help you diagnose the problem .

Benefits of utilizing startup metrics

Android uses the Time to initial display and Time to full display metrics to optimize cold and warm application startups. Android Runtime ( ART ) uses the data from these metrics to efficiently precompile code for optimization of future startups .
Faster startups lead to more sustained user interaction with your app, which reduces instances of early exiting, restarting the instance, or navigating away to a different app .

Android vitals

Android vitals can help improve your app’s performance by alerting you, via the Play Console, when your app’s startup times are excessive. Android vitals considers your app’s startup times excessive when the app’s :

  • Cold startup takes 5 seconds or longer.
  • Warm startup takes 2 seconds or longer.
  • Hot startup takes 1.5 seconds or longer.

Android vitals uses the Time to initial display metric and doesn’t report data for hot startups. For information on how Google Play collects Android vitals data, see the Play Console documentation .

Time to initial display

The time to initial display ( TTID ) metric measures the time it takes for an application to produce its first frame, including process initialization ( if a cold start ), activity creation ( if cold / warm ), and displaying first frame .

How to retrieve TTID

In Android 4.4 (API level 19) and higher, logcat includes an output line
containing a value called Displayed. This value represents the amount of time
elapsed between launching the process and finishing drawing the corresponding
activity on the screen. The elapsed time encompasses the following sequence of
events:

  • Launch the process.
  • Initialize the objects.
  • Create and initialize the activity.
  • Inflate the layout.
  • Draw your application for the first time.

The reported log line looks similar to the following example :

ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms

If you’re tracking logcat output from the command line, or in a terminal, finding the elapsed time is straightforward. To find elapsed time in Android Studio, you must disable filters in your logcat view. Disabling the filters is necessary because the system server, not the app itself, serves this log .

Once you’ve made the appropriate settings, you can easily search for the correct
term to see the time. Figure 2 shows how to disable filters, and, in the second
line of output from the bottom, an example of logcat output of the
Displayed time.


Figure 2: Disabling filters, and
finding the `Displayed` value in logcat.

The Displayed metric in the logcat output does not necessarily capture
the amount of time until all resources are loaded and displayed: it leaves out
resources that are not referenced in the layout file or that the app creates
as part of object initialization. It excludes these resources because loading
them is an inline process, and does not block the app’s initial display.

Sometimes the Displayed line in the logcat output contains an additional field for
total time. For example:

ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms (total +1m22s643ms)

In this case, the first time measurement is only for the activity that was first
drawn. The total time measurement begins at the app process start, and could
include another activity that was started first but did not display anything to
the screen. The total time measurement is only shown when there is a
difference between the single activity and total startup times.

You can also measure the time to initial display by running your app with the
ADB Shell Activity Manager command. Here’s an
example:

adb [-d|-e|-s ] shell am start -S -W
com.example.app/.MainActivity
-c android.intent.category.LAUNCHER
-a android.intent.action.MAIN

The Displayed metric appears in the logcat output as before. Your terminal
window should also display the following:

Starting: Intent
Activity: com.example.app/.MainActivity
ThisTime: 2044
TotalTime: 2044
WaitTime: 2054
Complete

The -c and -a arguments are optional and let you specify
and

Time to full display

The Time to full display ( TTFD ) metric measures the time taken by the application to produce its first frame with full content, including content loaded asynchronously after the first frame. Generally, this is primary list content loaded from the network, as reported by the app .

How to retrive TTFD

You can use the
reportFullyDrawn()
method to measure the elapsed time between application launch and complete
display of all resources and view hierarchies. This can be valuable in cases
where an app performs lazy loading. In lazy loading, an app does not block the
initial drawing of the window, but instead asynchronously loads resources and
updates the view hierarchy.

If, due to lazy loading, an app’s initial display does not include all resources, you might consider the completed loading and display of all resources and views as a separate metric : For example, your UI might be fully loaded, with some text drawn, but not yet display images that the app must fetch from the network .

To address this concern, you can manually call reportFullyDrawn() to let the
system know that your activity is finished with its lazy loading. When you use
this method, the value that logcat displays is the time elapsed from the
creation of the application object to the moment reportFullyDrawn() is called.
Here’s an example of the logcat output:

system_process I/ActivityManager: Fully drawn {package}/.MainActivity: +1s54ms

The logcat output sometimes includes a total time, as discussed in
Time to initial display.

If you learn that your display times are slower than you’d like, you can go on to try to identify the bottlenecks in the startup process .

Identifying bottlenecks

A good way to look for bottlenecks is to use the Android Studio CPU Profiler. For information, see Inspect CPU activity with CPU Profiler .

You can also gain insight into potential bottlenecks through inline tracing inside of your apps’
and activities’ onCreate() methods. To learn about inline tracing, see the
documentation for the Trace functions, and the
overview of system tracing.

Be aware of common issues

This section discusses several issues that often affect apps ’ startup performance. Thes e issues chiefly concern initializing app and activity objects, as well as the loading of screens .

Heavy app initialization

Launch performance can suffer when your code overrides the Application
object, and executes heavy work or complex logic when initializing that object.
Your app may waste time during startup if your Application subclasses perform
initializations that don’t need to be done yet. Some initializations may be
completely unnecessary: for example, initializing state information for the
main activity, when the app has actually started up in response to an intent.
With an intent, the app uses only a subset of the previously initialized state
data.

Other challenges during app initialization include garbage-collection events that are impactful or numerous, or disk I / O happening concurrently with initialization, further blocking the initialization process. Garbage collection is especially a consideration with the Dalvik runtime ; the Art runtime performs garbage collection concurrently, minimizing that operation’s impact .

Diagnosing the problem

You can use method tracing or inline tracing to try to diagnose the problem .

Method tracing

Running the CPU Profiler reveals that the
callApplicationOnCreate()
method eventually calls your com.example.customApplication.onCreate
method. If the tool shows that these
methods are taking a long time to finish executing, you should explore further
to see what work is occurring there.

Inline tracing

Use inline tracing to investigate likely culprits including :

  • Your app’s initial onCreate() function.
  • Any global singleton objects your app initializes.
  • Any disk I/O, deserialization, or tight loops that might be occurring during the bottleneck.

Solutions to the problem

Whether the problem lies with unnecessary initializations or with disk I / O, the solution is lazy initialization. In other words, you should only initialize objects that are immediately needed. Instead of creating global static objects, move to a singleton pattern where the app initializes objects only the first time it needs them .
Also, consider using a dependency injection framework like Hilt that creates objects and dependencies when they are injected for the first time .
If your app uses content providers to initialize app components at startup, consider using the App Startup library instead .

Heavy activity initialization

Activity creation often entails a lot of high-overhead work. Often, there are opportunities to optimize this work to achieve performance improvements. Such common issues include :

  • Inflating large or complex layouts.
  • Blocking screen drawing on disk, or network I/O.
  • Loading and decoding bitmaps.
  • Rasterizing VectorDrawable objects.
  • Initialization of other subsystems of the activity.

Diagnosing the problem

In this case, as well, both method tracing and inline tracing can prove useful .

Method tracing

When using the CPU Profiler, pay attention to your app’s
Application subclass constructors and
com.example.customApplication.onCreate() methods.

If the tool shows that these methods are taking a long time to finish executing, you should explore further to see what work is occurring there .

Inline tracing

Use inline tracing to investigate likely culprits including :

  • Your app’s initial onCreate() function.
  • Any global singleton objects it initializes.
  • Any disk I/O, deserialization, or tight loops that might be occurring during the bottleneck.

Solutions to the problem

There are many potential bottlenecks, but two common problems and remedies are as follows :

  • The larger your view hierarchy, the more time the app takes to inflate it. Two steps you can take to address this issue are :
    • Flattening your view hierarchy by reducing redundant or nested layouts .
    • Not inflating parts of the. U. that do not need to be visible during launch. Instead, use a ViewStub object as a placeholder for sub-hierarchies that the app can inflate at a more appropriate time.

  • Having all of your resource initialization. on th. main thread can also slow downstartup. You can address this issue as follows :
    • Move all resource initialization so that the app can perform it lazily on a different thread.
    • Allow the appto. load and display your views, and thenlater update visual properties that are dependent on bitmaps and other resources.

Custom splash screens

You may see extra time added during startup if you have previously used one of the following methods to implement a custom splash màn hình hiển thị in Android 11 ( API level 30 ) or lower :

Starting with Android 12, migrating to the SplashScreen
API is required. This API enables a faster startup time, and also allows you to
tweak your splash screen in the following ways:

Furthermore, the compat library backports the SplashScreen API to enable backward-compatibility and to create a consistent look and feel for splash màn hình hiển thị display across all Android versions .
See the Splash màn hình hiển thị migration guide for details .

Source: https://vh2.com.vn
Category : Ứng Dụng