Android APP啓動優化一 APP啓動測量

1 前言

Android APP 啓動優化是性能優化的重要方向之一,特別是對於原生應用來講,控制在1s內以內對一個APP的競爭力很重要,下面從幾個角度來講APP的啓動優化,先看APP的啓動類別

2 APP啓動類別

參考google官方文檔App startup time,官方對APP啓動主要做了三種分類

1.冷啓動

冷啓動指的是APP從頭開始啓動,沒有創建進程,需要完整的走進程創建,ActivityThread創建,Application創建等生命週期的啓動,冷啓動耗時最多
啓動時分爲以下幾步
1 加載和啓動app
2 加載空白window
3 創建App進程

隨後進行如下步驟
1 創建Application對象,並回調其方法
2 啓動主線程
3 創建MainActivity
4 初始化View和加載佈局
5 佈局屏幕
6 首幀繪製
冷啓動一般流程如下:
在這裏插入圖片描述

2.暖啓動

當應用中的Activity被銷燬,但在內存中常駐時,應用的啓動方式就會變爲暖啓動。相比冷啓動,暖啓動過程減少了對象初始化、佈局加載等工作,啓動時間更短。但啓動時,系統依然會展示一個空白背景,直到第一個Activity的內容呈現爲止。因此暖啓動一般會走Activity的onCreate生命週期,暖啓動耗時較少,一般需要注意在Activity的生命週期中不要做耗時操作即可。

3.熱啓動

相比暖啓動,熱啓動時應用做的工作更少,啓動時間更短。熱啓動產生的場景很多,常見如:用戶使用返回鍵退出應用,然後馬上又重新啓動應用。熱啓動較快,一般需要注意在onResmue中不要做耗時操作

對於系統流程我們一般無法改變,因此對於三方應用來說,APP啓動優化的主要方向在Application的生命週期和Activity的生命週期中

3 APP啓動測量

前面講了APP啓動的類別,現在要講如何粗略或者詳細的測量一個APP的啓動時間,一般來說有以下幾種辦法

1 adb 命令測量

adb shell am start –W packageName/首屏Activity
例如:

adb shell am start –W com.qiyei.mall/com.qiyei.mall.ui.activity. MainActivity

執行如下:
在這裏插入圖片描述
MainActivity 是首頁,HomeActivity是主頁

ThisTime: 最後一個Activity啓動耗時
TotalTime: 啓動所有Activity耗時
WaitTime: AMS啓動Activity耗時

2 ActivityManager中日誌打印

ActivityManager中會打印啓動activity的時間

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

相關的代碼如下:
ActivityRecord#reportLaunchTimeLocked()

    private void reportLaunchTimeLocked(final long curTime) {
        final ActivityStack stack = getStack();
        if (stack == null) {
            return;
        }
        final long thisTime = curTime - displayStartTime;
        final long totalTime = stack.mLaunchStartTime != 0
                ? (curTime - stack.mLaunchStartTime) : thisTime;
        if (SHOW_ACTIVITY_START_TIME) {
            Trace.asyncTraceEnd(TRACE_TAG_ACTIVITY_MANAGER, "launching: " + packageName, 0);
            EventLog.writeEvent(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(TAG, sb.toString());
        }
        mStackSupervisor.reportActivityLaunchedLocked(false, this, thisTime, totalTime);
        if (totalTime > 0) {
            //service.mUsageStatsService.noteLaunchTime(realActivity, (int)totalTime);
        }
        displayStartTime = 0;
        stack.mLaunchStartTime = 0;
    }

可以看到打印的是,這個時間從應用啓動(創建進程)開始計算,到完成視圖的第一次繪製的時間

3 手動打點

這個思想也比較簡單,由於應用層能接觸到的最早方法是Application#attachBaseContext()而結束時間,我們可以認爲是Activity#onWindowFocusChanged或者View的真正繪製完成,因此我們可以在attachBaseContext記錄一下時間,在onWindowFocusChanged中或者View繪製完成後記錄結束時間,只是需要注意怎麼處理View的onDraw監聽問題

4 Systrace測量

這個可以參考官方文章systrace來進行操作,注意systrace需要python環境,因此需要先搭建好python環境。下面是一個systrace的例子
在這裏插入圖片描述
可以看到,systrace可以看到更多的系統調用過程,例如這裏可以看到進程Zygote創建和ActivityThread的初始化時間等,有助於分析啓動時當時系統的狀態。

這一篇就介紹到這,下一篇會介紹TraceView和Systrace的簡單使用

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章