App Startup optimization

Start the way

  • Cold start

    When an application is started, the system creates a new process and assigns it to the application if there is no process running on the background (for example, the process is killed or started for the first time)

  • A warmer

    When you start an application, there is an application process in the background. For example, if you press the Back or home key, the application will exit, but the application process will remain in the background for viewing in the task list. Therefore, in the case of an existing application process, this startup will start the application from the existing process

  • Warm start

    Hot starts do less work and take less time than warm starts. Hot start can occur in many scenarios. For example, a user uses the back key to exit an application and then immediately restart the application

Hot starts and warm starts do not create or initialize applications because they start from an existing process

Usually in our discussion, warm start and hot start will be collectively referred to as hot start, because the difference between warm start and hot start is very small. If you do not pay special attention to the start process, there is no direct difference in user experience and sensory, but inframeworkLayers are executed differently. The optimization point is also around the cold start and hot start to do, the warm start and hot start collectively referred to as hot start

The other thing is, in absolute time,appThe first boot after installation will be the most time consuming because the first boot creates a new database,spFiles, various caches, configurations, etc


Blank screen/blank screen problem

  • White screen or black screen, depending on whether the app’s Theme is dark or light

  • Blank screen caused by Android Studio

    2. In the X era, instant Run may cause a blank screen, but this problem does not occur in complete APK packages

  • White screen/black screen caused by cold startup

    The time between the moment you click on your app and when the system calls Activity.oncreate (). During this time, WindowManager loads the windowBackground in the App theme style as the app preview element, and then actually loads the Activity layout

  • White or black screen caused by warm startup or hot startup

    This is not so obvious on well-configured phones with plenty of memory, but low-end phones or memory constraints can still have a “flash screen” effect, which lasts for a short time and passes by

To optimize the

I divide cold start optimization into controllable stage and uncontrollable stage

  • Uncontrollable stage

    Between clicking on the app and initializing the Application, the system takes over, forks new processes from the Zygote process, collects GC, etc., all of which have nothing to do with our app

  • Controllable phase

    The initialization of Application begins as shown below

    As can be seen from the figure above, there are at least two onCreate in the whole cold start process, namely Application and Activity, and the whole process is controllable. So, the more things the onCreate method does, the longer the cold start takes

The startup time

  • Logcat Automatically prints

    Starting with Android 4.4 (API 19), Logcat automatically prints out the app startup time for us. This time is calculated from the start of the application (the creation process) until the first drawing of the view (that is, the Activity content is visible to the user) is completed

    • Cold start:
    04-25 14:53:09.317 869-1214/? I/ActivityManager: Displayed cn.com.dhc.danlu/.shell.activity.InitializeActivity: +4s256ms
    04-25 14:53:11.077 869-1214/? I/ActivityManager: Displayed cn.com.dhc.danlu/.shell.main.MainActivity: +559ms
    Copy the code
    • Thermal activation:
    04-25 14:53:20.407 869-1214/? I/ActivityManager: Displayed cn.com.dhc.danlu/.shell.activity.InitializeActivity: +178ms
    04-25 14:53:22.447 869-1214/? I/ActivityManager: Displayed cn.com.dhc.danlu/.shell.main.MainActivity: +131ms
    Copy the code
    • The log information from com. Android. Server. Am. ActivityRecord# reportLaunchTimeLocked (long curTime) in printed:
    private void reportLaunchTimeLocked(final long curTime) {
       final ActivityStack stack = task.stack;
       final long thisTime = curTime - displayStartTime;
       final longtotalTime = stack.mLaunchStartTime ! =0
               ? (curTime - stack.mLaunchStartTime) : thisTime;
       if (ActivityManagerService.SHOW_ACTIVITY_START_TIME) {
           Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, "launching".0);
           EventLog.writeEvent(EventLogTags.AM_ACTIVITY_LAUNCH_TIME,
                   userId, System.identityHashCode(this), shortComponentName,
                   thisTime, totalTime);
           StringBuilder sb = service.mStringBuilder;
           sb.setLength(0);
           sb.append("Displayed ");
           sb.append(shortComponentName);
           sb.append(":");
           TimeUtils.formatDuration(thisTime, sb);
           if(thisTime ! = totalTime) { sb.append(" (total ");
               TimeUtils.formatDuration(totalTime, sb);
               sb.append(")");
           }
           Log.i(ActivityManagerService.TAG, sb.toString());
       }
       mStackSupervisor.reportActivityLaunchedLocked(false.this, thisTime, totalTime);
       if (totalTime > 0) {
           //service.mUsageStatsService.noteLaunchTime(realActivity, (int)totalTime);
       }
       displayStartTime = 0;
       stack.mLaunchStartTime = 0;
    }
    
    // Normal time: Counts the time between the start of the Activity and the completion of the interface drawing
    // Total time: counts the time when the Normal time + Activity stack is established
    Copy the code
  • Measure the Activity start time

    The Activity of reportFullyDrawn ()

    We can call this method anywhere in the Activity to print the final time you want to see when a method is finished executing. It will print in Logcat how long it took from the time the APK was initialized to the time the reportFullyDrawn() method was called

    ActivityManager: Displayed com.Android.myexample/.StartupTiming: +768ms
    Copy the code

    Calling the reportFullyDrawn() method on 4.4 crashes (but the log will still print), indicating that the UPDATE_DEVICE_STATS permission is required, but not available

    try {
    reportFullyDrawn();
    } catch (SecurityException e) {
    }
    Copy the code
  • Local debug start time

    The above command can directly start the corresponding activity of the package name, but note that not all activities can be directly started using this command

    • Thermal activation:

    • Cold start:

    • Just focus on TotalTime
  • The adb screenrecord command

    • First start the beltbugreportOption (it can be found inframesTo add a timestamp – should beLIn)screenrecordThe command

    • And then clickappIcon, waitappDisplay,ctrl-CstopscreenrecordCommand, generated in the phone’s memoryaunch.mp4Video file, and thenpullTo the computer
    • Open the video frame by frame and note that there is one at the top of the videoframeThe time stamp. Keep going until you find outappUntil the icon is highlighted. At this point, the system has processed the click event on the icon and started to bootappNow, record the time of this frame. Keep playing the frame until you see itappThe wholeUIBy the first frame. Depending on the situation (whether there is a launch window, whether there is a launch screen, etc.). The actual order in which events and Windows occur may differ. For a simpleappFor example, you will see the launch window first and then fade outappThe realUI. At you seeUIAnd then the first frame is recorded, at this pointappThe layout and drawing are complete and ready to be displayed. It also records the time at which this frame occurred
    • Now let’s subtract these two times((UI displayed) - (icon tapped))getappAll the time from click to draw ready. Although this time includes the time before the process starts, at least it can be used with othersappTo compare

Thus, the cold startup time of app is about 4s, and the hot startup time is about 132ms.

Optimization scheme (for controlled area only)

  • Analysis from startup process

    Reduce two initializations in onCreate() and move some of the initializations to IntentService

  • Analysis from user experience

    Change the response of the app Home page by pressing the back button to respond to the Home button to save the country. Make the user think the app has actually quit, but it’s actually hitting the Home button. In this way, the next time you click the app icon, it will be directly evoked, without initialization operation, and you can mainly avoid going to the flash screen again. Refer to Meituan, wechat, QQ, Taobao, etc. (The effect is the same, but the way of implementation is unknown)

    • Weibo: Click the back button and after startupHomeKey operation is the same, bottom selectedtabThere is no auto-switch
    • Meituan: Click the back button and after startupHomeThe operation of the key is different. Select the key at the bottomtabI did auto-switch
    • QQ: Same as weibo
    • Taobao: after starting the home page to press the return key, will return to the firsttab“And then quit

To optimize

  • We set the theme of the launch screen to SplashTheme as recommended by the official Google documentation. This interface is the first one loaded after cold startup:

    The code in the topic looks like this:

    This theme is equivalent to losing an image as the background, that is, a Logo and Slogan image with a red background without a version number

    At this point, we have “eliminated” the white screen/black screen and replaced the cold startup white screen/black screen with the monotonous solid color background with the picture of the InitializeActivity interface that we are going to show to the user. The jump process from the system Window to our App uses the full-screen attribute to achieve a seamless jump

    It needs to be noted that after this step is done, the overall startup time does not have any reduction, the time remains the same, just said to the user experience to be a lot of friendly, no longer show a sudden white/black screen interface —— will pan swing to their app, APP too card, InitializeActivity takes so long to complete (what users don’t know is that the system Window interface and InitializeActivity are not the same interface)

    Of course, you can also use another way, that is to set the theme of the backgroud as transparent when the user clicks the icon to start, there is no change on the interface, because at this time the system starts the white screen/black screen interface background transparent —— pan to the system, too card, It’s amazing how long it took to click the icon to show the InitializeActivity

  • Next we see if the onCreate() of the Application and InitializeActivity has code that can be migrated to IntentService:

    • BaseApplication:

    As can be seen, in fact, there are not many logic, and all of them need to be initialized in the Application, so they cannot be raised separately for initialization. Only GrowingIO can be considered to be raised

    • MainApplication:

    Push initialization can be raised

    • InitializeActivity:

    At first glance, there is no time-consuming operation in onCreate, and several internal methods are required business logic. The only thing that can be moved is the internal delay time for interface stay, which is currently 2s and can be reduced to about 1s.

  • As a final step, the return key logic is handled in MainActivity.

    Replace the logic that really exits with pressing the Home button:

    This gives the user the illusion that they hit the back button to quit, but they never quit, and the app stays in the background and is called up the next time they click the icon

    There are a few things to note about this operation

    • inonRestartNeed to judgetabstate
    • inonSaveInstanceStateandonRestoreInstanceStateNeed to save and restore data, used to determine the user is the pointhomeorbackThese two operations need to be separated and savedtabstate
    • Broadcast monitoringHomeThe key events
    • .
  • The results of

    Cold start:

    Thermal activation:

    According to the figure above, the optimized cold start time is about3544ms, the hot start time is about127msCompared to the previous4121msAs well as151msThe white screen effect has also been removed.

    But actually the biggest improvement point is not the white screen optimization, because we did not putApplicationandActivityIn theonCreateThe logic is reduced and mentionedIntentServiceIn the.

    The biggest improvement is that we let users log outapp“, creating the illusion that the user actually quitapp“, but we’re actually hiding in the background, and we don’t have to go through them when they’re hot or warmInitializeActivityThe process enters the home page.


conclusion

  • Replace the blank screen with a picture
  • onCreateAvoid doing too many initializations, if necessaryIntentService
  • Home page ofBackandHomeThe actions of the key are faked so that the user pressesBackKey as if he quit, to reduce the next startup unnecessary action (Suggestion: Non-instant messaging and socialapp, this practice should be used with caution, because there may be suspected of rogue… (escape))
  • Activity#moveTaskToBack(true)

The resources

  • What does the “I/ActivityManager: Displayed… The activity… Comprised of + 850 ms “?

  • Launch-time performance

  • Android App startup time statistics

  • Android Performance Optimization – Startup process Cold start hot start

  • Android cold start process analysis and optimization of apps you should know


TODO

  • [] Inquiry: Why is the cold start time of Hello World project shorter than that of online project

Code portal