新聞中心
1 簡介

商南ssl適用于網(wǎng)站、小程序/APP、API接口等需要進行數(shù)據(jù)傳輸應(yīng)用場景,ssl證書未來市場廣闊!成為創(chuàng)新互聯(lián)的ssl證書銷售渠道,可以享受市場價格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:028-86922220(備注:SSL證書合作)期待與您的合作!
互聯(lián)網(wǎng)領(lǐng)域里有個八秒定律,如果網(wǎng)頁打開時間超過8秒,便會有超過70%的用戶放棄等待,對Android app而言,要求更加嚴格,如果系統(tǒng)無響應(yīng)時間超過5秒,便會出現(xiàn)ANR,APP可能會被強制關(guān)閉,因此,啟動時間作為一個重要的性能指標,關(guān)系著用戶的***體驗。
愛奇藝安卓APP非常重視啟動速度的優(yōu)化,本文將從啟動過程,啟動時間測量,啟動優(yōu)化,以及后續(xù)監(jiān)控等方面分享我們在啟動優(yōu)化方面積累的經(jīng)驗。
2 啟動模式
要準確的測量APP的啟動時間,首先我們要了解APP整個啟動過程。 啟動過程,一般可以分為以下三類:
從上圖可以看出,啟動過程中,Cold的模式下,生命周期中做的事情最多,啟動的時間最長,因此,我們以冷啟動來衡量APP啟動時間。啟動過程中,如何判斷哪些生命周期影響啟動速度呢?
3 啟動過程
我們知道,APP的啟動和運行,就是Linux系統(tǒng)創(chuàng)建進程和組件對象,并在UI線程中處理組件消息的過程。
啟動過程圖:
App的啟動過程,可以劃分為三個階段:
3.1 創(chuàng)建進程
當APP啟動時,如果當前app的進程不存在,便會創(chuàng)建新的進程;App主進程啟動后,如果啟動某個組件,并且該組件設(shè)置了android:process屬性,組件所運行的進程不存在,也會創(chuàng)建新的進程。
需要注意的是,如果在啟動階段,初始化的組件中,包含了多個進程,便會創(chuàng)建多次進程,BindApplication操作也會重復(fù)執(zhí)行多次
3.2 創(chuàng)建UI線程及Handler
進程創(chuàng)建后,會通過反射,執(zhí)行ActivityThread入口函數(shù),創(chuàng)建Handler,并在當前線程中prepareMainLooper,并在Handler中接收組件的消息,我們來看一下Handler中處理的消息:
- LAUNCH_ACTIVITY,啟動,執(zhí)行Activity
- RESUME_ACTIVITY,恢復(fù)Activity
- BIND_APPLICATION,啟動app
- BIND_SERVICE,Service創(chuàng)建, onBind
- LOW_MEMORY,內(nèi)存不足,回收后臺程序
sMainThreadHandler中,處理的消息很多,這里只羅列了,可能在啟動階段可能會執(zhí)行的操作, 這些操作都是運行在Main Thread中,對啟動而言,屬于阻塞性的。
Activity生命周期,自然需要在啟動階段執(zhí)行,但,對于Service的創(chuàng)建,Trim_memory回調(diào),廣播接收等操作,就需要重點考慮,其操作耗時性。
3.3 Activity運行及繪制
前兩個過程,創(chuàng)建進程和UI線程及Handler,都是由系統(tǒng)決定的,對APP開發(fā)者而言,并不能控制其執(zhí)行時間,在本階段,執(zhí)行BindApplication,和Acitivity生命周期,都是可以由開發(fā)者自定義。
Activity執(zhí)行到onResume之后,會執(zhí)行至ViewRootImpl,執(zhí)行兩次performTraversals,第二次traversal操作中,會執(zhí)行performDraw操作,同時通知RenderThread線程執(zhí)行繪制.
從啟動的三個階段,我們可以看出,啟動啟動時間的長短,決定因素在于,主線程中所做事情消耗的時間的多少,所以,我們的優(yōu)化工作主要集中在,排查主線程中耗時性的工作,并進行合理的優(yōu)化。Android手機,系統(tǒng)的資源是有限的,過多的異步線程,會搶占CPU,導(dǎo)致主線程執(zhí)行時間片間隔增大。同樣的,內(nèi)存消耗狀態(tài),GC頻率,也會影響啟動的時間。
4 分析及測量
通過上述的源碼的解讀,我們已經(jīng)了解了啟動過程,以及可能引起啟動過慢的原因。接下來介紹一些常用的分析手段及時間測量方法。
啟動分析工具,主要使用SysTrace,具體的使用方法,請參考官網(wǎng)文檔https://developer.android.com/studio/command-line/systrace。
4.1 SysTrace分析技巧
4.1.1 UI Thread 顏色顯示
- 綠色:Running
- 白色:Sleeping
- 棕色:Uninterruptible Sleep
- 橙色:Uninterruptible Sleep - Block I/O
其中10ms以內(nèi)的,較短時間的Sleeping狀態(tài),不用關(guān)注,可能是由于CPU調(diào)度的時間片分配間隔引起的;較長時間的Block I/O和Sleep狀態(tài),可以確定有阻塞啟動的邏輯在這個階段運行,需要進一步對代碼進行分析定位。
4.1.2 查看CPU狀態(tài)及線程運行時長
查看CPU占用狀態(tài):
線程執(zhí)行:
通過該階段密集程度,反映出CPU占用率,也能在一定程度上反映出該階段執(zhí)行時間被阻塞情況;線程執(zhí)行情況統(tǒng)計,可以查看線程執(zhí)行時間排名,對執(zhí)行時間較長的子線程進行優(yōu)化。
4.2 SysTrace啟動時間
在SysTrace圖中,UI Thread中包含了bindApplication,activityStart,traversal等操作,RenderThread中包含DrawFrame等操作。這些TAG節(jié)點是源碼已經(jīng)添加的,可參考#3.2中介紹。
Trace上啟動時間:從bindApplication至第二次traversal完成,可認為UI***次繪制完成,啟動完成。選中開始點和結(jié)束點,可以查看過程消耗的時間。
4.3 adb shell am start -W
在統(tǒng)計APP啟動時間時,系統(tǒng)為我們提供了adb命令,可以輸出啟動時間
TotalTime:表示新應(yīng)用啟動的耗時,包括新進程的啟動和 Activity 的啟動,但不包括前一個應(yīng)用 Activity pause 的耗時
系統(tǒng)在繪制完成后,ActivityManagerService會回調(diào)該方法,統(tǒng)計時間不如SysTrace準確,但是能夠方便我們通過腳本多次啟動測量TotalTime,對比版本間啟動時間差異。
4.4 埋點
通過APP啟動生命周期中,關(guān)鍵位置加入時間點記錄,達到測量目的。
4.5 錄屏
錄屏方式收集到的時間,更接近于用戶的真實體感。
5 優(yōu)化
為了讓用戶在進入APP之后,更快更流暢的使用服務(wù),所以會在啟動過程中,提前對一些基礎(chǔ)庫和組建進行初始化操作,這就意味著系統(tǒng)有限的資源會被搶占,影響啟動時間。啟動時間的優(yōu)化,是一個平衡性能和體驗的過程。
通過Systrace工具分析,我們發(fā)現(xiàn)愛奇藝愛奇藝安卓APP啟動過程中一些問題,接下來,我們就結(jié)合具體的業(yè)務(wù)實踐,進行啟動問題進行優(yōu)化。
5.1 區(qū)分進程初始化Application
由#3我們了解到,對于一個app而言,App內(nèi)組件可以運行在不同的進程之中。舉個例子: 一個APP擁有主進程,插件進程,下載進程三個進程,會在啟動階段創(chuàng)建相應(yīng)的組件,但只有一個QYApplication繼承自系統(tǒng)Application,創(chuàng)建三次進程,QYApplication中attach(),onCreate()方法都會被執(zhí)行三次。
每個進程說需要初始化的內(nèi)容肯定是不一樣的,所以,為了防止資源的浪費,我們需要區(qū)分進程,初始化Appcation.
成果:對多進程應(yīng)用而言,通過對初始化內(nèi)容進行梳理,合理區(qū)分初始化,會大幅減少內(nèi)存和CPU占用。
5.2 異步處理耗時任務(wù)
子線程處理耗時任務(wù),主線程做的事情越少,越早進入Acitivity繪制階段,界面越早展現(xiàn)。
注意:
- 不在主線程做耗時任務(wù),如文件,網(wǎng)絡(luò)等
- 啟動階段初始化任務(wù),盡量在異步線程處理
- 主線程,不用等待或者依賴于子線程任務(wù)
進一步優(yōu)化:可以自建線程池,維持一定線程個數(shù),管理任務(wù)隊列。
5.3 防止多線程搶占CPU
Android系統(tǒng)資源有限,特別是CPU資源,理論上來說,UI線程執(zhí)行的任務(wù),也無法保證一直被調(diào)度狀態(tài),當并發(fā)的線程數(shù)過多,UI線程時間片會更短,從而導(dǎo)致啟動時間被變慢。
下面羅列一些常見,容易造成CPU被搶占的場景:
成果:通過對執(zhí)行時間較久,執(zhí)行頻率的業(yè)務(wù)進行優(yōu)化,將CPU占有率維持在合理的程度,會大幅減少啟動時間,減少300ms以上。
5.4 系統(tǒng)API使用
部分系統(tǒng)的API使用是阻塞性的,文件很小可能無法感知,當文件過大,或者使用頻繁時,可能造成阻塞。例如:
SharedPreference.Editor提交操作:
- commit方法屬于屬于阻塞性質(zhì)API,建議使用apply。
此外,我們知道,SP文件的存儲是一個XML文件,以key-value形式存儲,當業(yè)務(wù)過多時,需要拆分為多個文件存儲,防止文件過大,出現(xiàn)讀取耗時及ANR。
進一步優(yōu)化,可對啟動階段,頻繁的SP操作在內(nèi)存中,統(tǒng)一提交。
AssetManager.open操作: Android開發(fā)中,我們有時會將資源文件放在assets目錄中,然后使用open操作讀取文件,如果文件過大,需要在異步線程中執(zhí)行。
成果:隨著業(yè)務(wù)量日積月累,正常的系統(tǒng)API的使用,也可能出現(xiàn)問題,通過排除,可減少50-100ms。
5.5 精簡布局
布局的復(fù)雜程度,直接影響繪制的時間。
舉個例子,在啟動過程中,會有需要大的背景圖,只有***次安裝時使用,后續(xù)屬性設(shè)置為android:visibility="gone",但是,雖然設(shè)置了gone屬性,不會顯示,但依舊會被解析。
建議:
減少布局層次
無用資源使用ViewStub,使用時加載
- 成果:啟動階段的布局較簡單,通過優(yōu)化背景圖片的加載,減少50-100ms。
5.6 Service延后初始化
App啟動中過程中,經(jīng)常進行Service初始化操作,由于Service使用一般不涉及界面,可能會認為初始化生命周期不在主線程中,其實不然,在3.2的啟動過程源碼介紹中講到,Service的生命周期,也屬于主線程Handler接收的Message之一。
- 建議:Service生命周期中,注意邏輯執(zhí)行時間性能優(yōu)化,初始化盡量延后。
- 成果:取決于初始化Service的生命周期執(zhí)行時間,可減少200ms以上。
5.7 將任務(wù)delay至首頁繪制完成后
對于APP首頁展示不需要的初始化邏輯,可延后至首頁繪制完成后初始化。
注意:
需要post兩次才能保證在***次繪制之后顯示,因為,系統(tǒng)繪制會執(zhí)行兩次Performtraversal。
進一步優(yōu)化:可將業(yè)務(wù)邏輯的初始化劃分為,首頁繪制后,5s,10s,20s三個階段分別初始化,防止首頁繪制執(zhí)行任務(wù)過多造成掉幀。
成果:釋放繪制階段的CPU,可將復(fù)雜的繪制提前200ms以上。
6 監(jiān)控
穩(wěn)定的用戶體驗依賴于持續(xù)的監(jiān)控,愛奇藝為監(jiān)控啟動性能建立了一套監(jiān)控體系,測試,工具,開發(fā)等幾個團隊從不同的緯度搭建不同的監(jiān)控方案
- 測試:錄屏,從用戶的真實體驗角度,獲取最準確的啟動時間。
- 實時監(jiān)控:通過埋點,大數(shù)據(jù)采樣投遞獲取真實線上環(huán)境數(shù)據(jù),從地域,時間,機型,app版本,系統(tǒng)版本等各個緯度對啟動時間進行監(jiān)控。
- 腳本測試:通過對腳本,對同一收集多次啟動數(shù)據(jù)進行收集,通過不同版本間的對比,監(jiān)控啟動時間的變化情況。
7 SysTrace擴展
SysTrace通過TAG節(jié)點可以清晰展現(xiàn),啟動過程以及方法執(zhí)行時間,但是,從發(fā)現(xiàn)問題,然后通過節(jié)點去定位問題,是一件很繁瑣的工作,如果你們工程編譯又比較慢,簡直讓人崩潰。
7.1 自動化TAG注入
在Android工程編譯的過程中,指定class,在方法前后,自動化插入Trace節(jié)點,統(tǒng)計方法執(zhí)行時間。
流程:
- 在編譯的過程中,插入自定義Task任務(wù),
- 讀取配置文件,文件中包含了需要注入java文件名和路徑名和method
- 找到需要注入的class文件,然后通過ASM改變字節(jié)碼,方法前后,插入自定義自定義方法
通過工具的操作,能夠做到不用修改原有工程文件,自動在打包時注入TAG節(jié)點和邏輯代碼,配置文件可以循環(huán)利用,提高分析效率,節(jié)能環(huán)保。
8 優(yōu)化結(jié)果
啟動時間,由于不同的機型性能同,Android系統(tǒng)版本不同,同一APP版本啟動時間,相差很大,所以統(tǒng)計一般以同一手機,不同版本做比較,盡量保證手機狀態(tài)一致。
SysTrace手機優(yōu)化時間對比:
腳本多次啟動時間收集對比:
經(jīng)過多個版本的持續(xù)優(yōu)化,有無廣告兩種不同的場景下,啟動時間分別減少40%和35%,啟動速度得到了較大的提升。
9 總結(jié)
啟動時間的優(yōu)化和監(jiān)控,是一項長期的任務(wù),需要對異常的情況進行分析,對可能造成阻塞的代碼邏輯進行合理的優(yōu)化,非常感謝各個業(yè)務(wù)團隊支持和配合。
新聞名稱:愛奇藝Android客戶端啟動優(yōu)化與分析
文章URL:http://www.5511xx.com/article/dhggoio.html


咨詢
建站咨詢
