1page.title=Launch-Time Performance 2@jd:body 3 4<div id="qv-wrapper"> 5<div id="qv"> 6 7<h2>In this document</h2> 8<ol> 9<li><a href="#internals">Launch Internals</a> 10 <ol> 11 <li><a href="#cold">Cold start</a></li> 12 <li><a href="#warm">Warm start</a></li> 13 <li><a href="#lukewarm">Lukewarm start</a></li> 14 </ol> 15</li> 16<li><a href="#profiling">Profiling Launch Performance</a> 17 <ol> 18 <li><a href="#time-initial">Time to initial display</a></li> 19 <li><a href="#time-full">Time to full display</a></li> 20 </ol> 21</li> 22<li><a href="#common">Common Issues</a> 23 <ol> 24 <li><a href="#heavy-app">Heavy app initialization</a></li> 25 <li><a href="#heavy-act">Heavy activity initialization</a></li> 26 <li><a href="#themed">Themed launch screens</a></li> 27 </ol> 28 </li> 29</ol> 30</div> 31</div> 32 33<p> 34Users expect apps to be responsive and fast to load. An app with a slow startup 35time doesn’t meet this expectation, and can be disappointing to users. This 36sort of poor experience may cause a user to rate your app poorly on the Play 37store, or even abandon your app altogether. 38</p> 39 40<p> 41This document provides information to help you optimize your app’s launch time. 42It begins by explaining the internals of the launch process. Next, it discusses 43how to profile startup performance. Last, it describes some common startup-time 44issues, and gives some hints on how to address them. 45</p> 46 47<h2 id="internals">Launch Internals</h2> 48 49<p> 50App launch can take place in one of three states, each affecting how 51long it takes for your app to become visible to the user: cold start, 52warm start, and lukewarm start. In a cold start, your app starts from scratch. 53In the other states, the system needs to bring the app from the background to 54the foreground. We recommend that you always optimize based on an assumption of 55a cold start. Doing so can improve the performance of warm and lukewarm starts, 56as well. 57</p> 58 59<p> 60To optimize your app for fast startup, it’s useful to understand what’s 61happening at the system and app levels, and how they interact, in each of 62these states. 63</p> 64 65<h3 id="cold">Cold start</h3> 66 67<p> 68A cold start refers to an app’s starting from scratch: the system’s process 69has not, until this start, created the app’s process. Cold starts happen in 70cases such as your app’s being launched for the first time since the device 71booted, or since the system killed the app. This type of start presents the 72greatest challenge in terms of minimizing startup time, because the system 73and app have more work to do than in the other launch states. 74</p> 75 76<p> 77At the beginning of a cold start, the system has three tasks. These tasks are: 78</p> 79 80<ol style="1"> 81 <li>Loading and launching the app.</li> 82 <li>Displaying a blank starting window for the app immediately after launch. 83 </li> 84 <li>Creating the app 85 <a href="{docRoot}guide/components/processes-and-threads.html#Processes"> 86 process.</a></li> 87</ol> 88<br/> 89<p> 90As soon as the system creates the app process, the app process is responsible 91for the next stages. These stages are: 92</p> 93 94<ol style="1"> 95 <li>Creating the app object.</li> 96 <li>Launching the main thread.</li> 97 <li>Creating the main activity.</li> 98 <li>Inflating views.</li> 99 <li>Laying out the screen.</li> 100 <li>Performing the initial draw.</li> 101</ol> 102 103<p> 104Once the app process has completed the first draw, the system process swaps 105out the currently displayed background window, replacing it with the main 106activity. At this point, the user can start using the app. 107</p> 108 109<p> 110Figure 1 shows how the system and app processes hand off work between each 111other. 112</p> 113<br/> 114 115 <img src="{@docRoot}topic/performance/images/cold-launch.png"> 116 <p class="img-caption"> 117 <strong>Figure 1.</strong> A visual representation of the important parts of 118 a cold application launch. 119 </p> 120 121<p> 122Performance issues can arise during creation of the app and 123creation of the activity. 124</p> 125 126<h4 id="app-creation">Application creation</h4> 127 128<p> 129When your application launches, the blank starting window remains on the screen 130until the system finishes drawing the app for the first time. At that point, 131the system process swaps out the starting window for your app, allowing the 132user to start interacting with the app. 133</p> 134 135<p> 136If you’ve overloaded {@link android.app.Application#onCreate() Application.oncreate()} 137in your own app, the app starts by calling this 138method on your app object. Afterwards, the app spawns the main thread, also 139known as the UI thread, and tasks it with creating your main activity. 140</p> 141 142<p> 143From this point, system- and app-level processes proceed in accordance with 144the <a href="{docRoot}guide/topics/processes/process-lifecycle.html"> 145app lifecycle stages</a>. 146</p> 147 148<h4 id="act-creation">Activity creation</h4> 149 150<p> 151After the app process creates your activity, the activity performs the 152following operations: 153</p> 154 155<ol style="1"> 156 <li>Initializes values.</li> 157 <li>Calls constructors.</li> 158 <li>Calls the callback method, such as 159 {@link android.app.Activity#onCreate(android.os.Bundle) Activity.onCreate()}, 160 appropriate to the current lifecycle state of the activity.</li> 161</ol> 162 163<p> 164Typically, the 165{@link android.app.Activity#onCreate(android.os.Bundle) onCreate()} 166method has the greatest impact on load time, because it performs the work with 167the highest overhead: loading and inflating views, and initializing the objects 168needed for the activity to run. 169</p> 170 171<h3 id="warm">Warm start</h3> 172 173<p> 174A warm start of your application is much simpler and lower-overhead than a 175cold start. In a warm start, all the system does is bring your activity to 176the foreground. If all of your application’s activities are still resident in 177memory, then the app can avoid having to repeat object initialization, layout 178inflation, and rendering. 179</p> 180 181<p> 182However, if some memory has been purged in response to memory trimming 183events, such as 184{@link android.content.ComponentCallbacks2#onTrimMemory(int) onTrimMemory()}, 185then those objects will need to be recreated in 186response to the warm start event. 187</p> 188 189<p> 190A warm start displays the same on-screen behavior as a cold start scenario: 191The system process displays a blank screen until the app has finished rendering 192the activity. 193</p> 194 195<h3 id="lukewarm">Lukewarm start</h3> 196 197<p> 198A lukewarm start encompasses some subset of the operations that 199take place during a cold start; at the same time, it represents less overhead 200than a warm start. There are many potential states that could be considered 201lukewarm starts. For instance: 202</p> 203 204<ul> 205 <li>The user backs out of your app, but then re-launches it. The process may 206 have continued to run, but the app must recreate the activity from scratch 207 via a call to 208 {@link android.app.Activity#onCreate(android.os.Bundle) onCreate()}.</li> 209 210 <li>The system evicts your app from memory, and then the user re-launches it. 211 The process and the Activity need to be restarted, but the task can 212 benefit somewhat from the saved instance state bundle passed into 213 {@link android.app.Activity#onCreate(android.os.Bundle) onCreate()}.</li> 214</ul> 215 216<h2 id="profiling">Profiling Launch Performance</h2> 217 218<p> 219In order to properly diagnose start time performance, you can track metrics 220that show how long it takes your application to start. 221</p> 222 223<h3 id="time-initial">Time to initial display</h3> 224 225<p> 226From Android 4.4 (API level 19), logcat includes an output line containing 227a value called {@code Displayed}. This value represents 228the amount of time elapsed between launching the process and finishing drawing 229the corresponding activity on the screen. The elapsed time encompasses the 230following sequence of events: 231</p> 232 233<ol style="1"> 234 <li>Launch the process.</li> 235 <li>Initialize the objects.</li> 236 <li>Create and initialize the activity.</li> 237 <li>Inflate the layout.</li> 238 <li>Draw your application for the first time.</li> 239</ol> 240 241<p> 242The reported log line looks similar to the following example: 243</p> 244 245<pre class="no-pretty-print"> 246ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms 247</pre> 248 249<p> 250If you’re tracking logcat output from the command line, or in a terminal, 251finding the elapsed time is straightforward. To find elapsed time in 252Android Studio, you must disable filters in your logcat view. Disabling the 253filters is necessary because the system server, not the app itself, serves 254this log. 255</p> 256 257<p> 258Once you’ve made the appropriate settings, you can easily search for the 259correct term to see the time. Figure 2 shows how to disable filters, and, 260in the second line of output from the bottom, an example of logcat output of 261the {@code Displayed} time. 262</p> 263<br/> 264 265 <img src="{@docRoot}topic/performance/images/displayed-logcat.png"> 266 <p class="img-caption"> 267 <strong>Figure 2.</strong> Disabling filters, and 268 finding the {@code Displayed} value in logcat. 269 </p> 270 271<p> 272The {@code Displayed} metric in the logcat output does not necessarily capture 273the amount of time until all resources are loaded and displayed: it leaves out 274resources that are not referenced in the layout file or that the app creates 275as part of object initialization. It excludes these resources because loading 276them is an inline process, and does not block the app’s initial display. 277</p> 278 279<h3 id="time-full">Time to full display</h3> 280 281<p> 282You can use the {@link android.app.Activity#reportFullyDrawn()} method to 283measure the elapsed time 284between application launch and complete display of all resources and view 285hierarchies. This can be valuable in cases where an app performs lazy loading. 286In lazy loading, an app does not block the initial drawing of the window, but 287instead asynchronously loads resources and updates the view hierarchy. 288</p> 289 290<p> 291If, due to lazy loading, an app’s initial display does not include all 292resources, you might consider the completed loading and display of all 293resources and views as a separate metric: For example, your UI might be 294fully loaded, with some text drawn, but not yet display images that the 295app must fetch from the network. 296</p> 297 298<p> 299To address this concern, you can manually call 300{@link android.app.Activity#reportFullyDrawn()} 301to let the system know that your activity is 302finished with its lazy loading. When you use this method, the value 303that logcat displays is the time elapsed 304since the creation of the application object, and the moment 305{@link android.app.Activity#reportFullyDrawn()} is called. 306</p> 307 308<p> 309If you learn that your display times are slower than you’d like, you can 310go on to try to identify the bottlenecks in the startup process. 311</p> 312 313<h4 id="bottlenecks">Identifying bottlenecks</h4> 314 315<p> 316Two good ways to look for bottlenecks are Android Studio’s Method Tracer tool 317and inline tracing. To learn about Method Tracer, see that tool’s 318<a href="{docRoot}studio/profile/am-methodtrace.html">documentation</a>. 319</p> 320 321<p> 322If you do not have access to the Method Tracer tool, or cannot start the tool 323at the correct time to gain log information, you can gain similar insight 324through inline tracing inside of your apps’ and activities’ {@code onCreate()} 325methods. To learn about inline tracing, see the reference documentation for 326the {@link android.os.Trace} functions, and for the 327<a href="{docRoot}studio/profile/systrace-commandline.html">Systrace</a> tool. 328</p> 329 330<h2 id="common">Common Issues</h2> 331 332<p> 333This section discusses several issues that often affect apps’ startup 334performance. These issues chiefly concern initializing app and activity 335objects, as well as the loading of screens. 336</p> 337 338<h3 id="heavy-app">Heavy app initialization</h3> 339 340<p> 341Launch performance can suffer when your code overrides the {@code Application} 342object, and executes heavy work or complex logic when initializing that object. 343Your app may waste time during startup if your Application subclasses perform 344initializations that don’t need to be done yet. Some initializations may be 345completely unnecessary: for example, initializing state information for the 346main activity, when the app has actually started up in response to an intent. 347With an intent, the app uses only a subset of the previously initialized state 348data. 349</p> 350 351<p> 352Other challenges during app initialization include garbage-collection events 353that are impactful or numerous, or disk I/O happening concurrently with 354initialization, further blocking the initialization process. Garbage collection 355is especially a consideration with the Dalvik runtime; the Art runtime performs 356garbage collection concurrently, minimizing that operation's impact. 357</p> 358 359<h4 id="diagnosing-1">Diagnosing the problem</h4> 360 361<p> 362You can use method tracing or inline tracing to try to diagnose the problem. 363</p> 364 365<h5>Method tracing</h5> 366 367<p> 368Running the Method Tracer tool reveals that the 369{@link android.app.Instrumentation#callApplicationOnCreate(android.app.Application) callApplicationOnCreate()} 370method eventually calls your {@code com.example.customApplication.onCreate} 371method. If the tool shows that these 372methods are taking a long time to finish executing, you should explore further 373to see what work is occurring there. 374</p> 375 376<h5>Inline tracing</h5> 377 378<p> 379Use inline tracing to investigate likely culprits including: 380</p> 381 382<ul> 383 <li>Your app’s initial {@link android.app.Application#onCreate()} 384 function.</li> 385 <li>Any global singleton objects your app initializes.</li> 386 <li>Any disk I/O, deserialization, or tight loops that might be occurring 387 during the bottleneck. 388</ul> 389 390 391<h4 id="solutions-1">Solutions to the problem</h4> 392 393<p> 394Whether the problem lies with unnecessary initializations or disk I/O, 395the solution calls for lazy-initializing objects: initializing only those 396objects that are immediately needed. For example, rather than creating global 397static objects, instead, move to a singleton pattern, where the app initalizes 398objects only the first time it accesses them. 399</p> 400 401<h3 id="heavy-act">Heavy activity initialization</h4> 402 403<p> 404Activity creation often entails a lot of high-overhead work. Often, there are 405opportunities to optimize this work to achieve performance improvements. Such 406common issues include: 407</p> 408 409<ul> 410 <li>Inflating large or complex layouts.</li> 411 <li>Blocking screen drawing on disk, or network I/O.</li> 412 <li>Loading and decoding bitmaps.</li> 413 <li>Rasterizing {@link android.graphics.drawable.VectorDrawable VectorDrawable} objects.</li> 414 <li>Initialization of other subsystems of the activity.</li> 415</ul> 416 417<h4 id="diagnosing-2">Diagnosing the problem</h4> 418 419<p> 420In this case, as well, both method tracing and inline tracing can prove useful. 421</p> 422 423<h5>Method tracing</h5> 424 425<p> 426When running the Method Tracer tool, the particular areas to 427focus on your your app’s {@link android.app.Application} subclass constructors and 428{@code com.example.customApplication.onCreate()} methods. 429</p> 430 431<p> 432If the tool shows that these methods are taking a long time to finish 433executing, you should explore further to see what work is occurring there. 434</p> 435 436<h5>Inline tracing</h5> 437 438<p> 439Use inline tracing to investigate likely culprits including: 440</p> 441 442<ul> 443 <li>Your app’s initial {@link android.app.Application#onCreate()} 444 function.</li> 445 <li>Any global singleton objects it initializes.</li> 446 <li>Any disk I/O, deserialization, or tight loops that might be occurring 447 during the bottleneck.</li> 448</ul> 449 450<h4 id="solutions-2">Solutions to the problem</h4> 451 452<p> 453There are many potential bottlenecks, but two common problems and remedies 454are as follows: 455</p> 456 457<ul> 458 <li>The larger your view hierarchy, the more time the app takes to inflate 459 it. Two steps you can take to address this issue are: 460 461 <ul> 462 <li>Flattening your view hierarchy by reducing redundant or nested 463 layouts.</li> 464 465 <li>Not inflating parts of the UI that do not need to be visible during 466 launch. Instead, use use a {@link android.view.ViewStub} object as a 467 placeholder for sub-hierarchies that the app can inflate at a more 468 appropriate time.</li> 469 </ul> 470 </li> 471 472 <li>Having all of your resource initialization on the main 473 thread can also slow down startup. You can address this issue as follows: 474 475 <ul> 476 <li>Move all resource initialization so that the app can perform it 477 lazily on a different thread.</li> 478 <li>Allow the app to load and display your views, and then later 479 update visual properties that are dependent on bitmaps and other 480 resources.</li> 481 </ul> 482 </li> 483 484<h3 id="themed">Themed launch screens</h3> 485 486 487<p> 488You may wish to theme your app’s loading experience, so that the app’s 489launch screen is thematically consistent with the rest of the app, instead of 490with the system theming. Doing so can hide a slow activity launch. 491</p> 492 493<p> 494A common way to implement a themed launch screen is to use the the 495{@link android.R.attr#windowDisablePreview} theme attribute to turn off 496the initial blank screen 497that the system process draws when launching the app. However, this approach 498can result in a longer startup time than apps that don’t suppress the preview 499window. Also, it forces the user to wait with no feedback while the activity 500launches, making them wonder if the app is functioning properly. 501</p> 502 503<h4 id="diagnosing-3">Diagnosing the problem</h4> 504 505<p> 506You can often diagnose this problem by observing a slow response when a user 507launches your app. In such a case, the screen may seem to be frozen, or to 508have stopped responding to input. 509</p> 510 511<h4 id="solutions-3">Solutions to the problem</h4> 512 513<p> 514We recommend that, rather than disabling the preview window, you 515follow the common 516<a href="http://www.google.com/design/spec/patterns/launch-screens.html#"> 517Material Design</a> patterns. You can use the activity's 518{@code windowBackground} theme attribute to provide a simple custom drawable 519for the starting activity. 520</p> 521 522<p> 523For example, you might create a new drawable file and reference it from the 524layout XML and app manifest file as follows: 525</p> 526 527<p>Layout XML file:</p> 528 529<pre> 530<layer-list xmlns:android="http://schemas.android.com/apk/res/android" android:opacity="opaque"> 531 <!-- The background color, preferably the same as your normal theme --> 532 <item android:drawable="@android:color/white"/> 533 <!-- Your product logo - 144dp color version of your app icon --> 534 <item> 535 <bitmap 536 android:src="@drawable/product_logo_144dp" 537 android:gravity="center"/> 538 </item> 539</layer-list> 540</pre> 541 542<p>Manifest file:</p> 543 544<pre> 545<activity ... 546android:theme="@style/AppTheme.Launcher" /> 547</pre> 548 549<p> 550The easiest way to transition back to your normal theme is to call 551{@link android.view.ContextThemeWrapper#setTheme(int) setTheme(R.style.AppTheme)} 552before calling {@code super.onCreate()} and {@code setContentView()}: 553</p> 554 555<pre class="no-pretty-print"> 556public class MyMainActivity extends AppCompatActivity { 557 @Override 558 protected void onCreate(Bundle savedInstanceState) { 559 // Make sure this is before calling super.onCreate 560 setTheme(R.style.Theme_MyApp); 561 super.onCreate(savedInstanceState); 562 // ... 563 } 564} 565</pre> 566