自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

愛(ài)奇藝Android客戶端啟動(dòng)優(yōu)化與分析

移動(dòng)開(kāi)發(fā) Android
愛(ài)奇藝安卓APP非常重視啟動(dòng)速度的優(yōu)化,本文將從啟動(dòng)過(guò)程,啟動(dòng)時(shí)間測(cè)量,啟動(dòng)優(yōu)化,以及后續(xù)監(jiān)控等方面分享我們?cè)趩?dòng)優(yōu)化方面積累的經(jīng)驗(yàn)。

1 簡(jiǎn)介

互聯(lián)網(wǎng)領(lǐng)域里有個(gè)八秒定律,如果網(wǎng)頁(yè)打開(kāi)時(shí)間超過(guò)8秒,便會(huì)有超過(guò)70%的用戶放棄等待,對(duì)Android APP而言,要求更加嚴(yán)格,如果系統(tǒng)無(wú)響應(yīng)時(shí)間超過(guò)5秒,便會(huì)出現(xiàn)ANR,APP可能會(huì)被強(qiáng)制關(guān)閉,因此,啟動(dòng)時(shí)間作為一個(gè)重要的性能指標(biāo),關(guān)系著用戶的***體驗(yàn)。

愛(ài)奇藝安卓APP非常重視啟動(dòng)速度的優(yōu)化,本文將從啟動(dòng)過(guò)程,啟動(dòng)時(shí)間測(cè)量,啟動(dòng)優(yōu)化,以及后續(xù)監(jiān)控等方面分享我們?cè)趩?dòng)優(yōu)化方面積累的經(jīng)驗(yàn)。

2 啟動(dòng)模式

要準(zhǔn)確的測(cè)量APP的啟動(dòng)時(shí)間,首先我們要了解APP整個(gè)啟動(dòng)過(guò)程。 啟動(dòng)過(guò)程,一般可以分為以下三類:

愛(ài)奇藝Android客戶端啟動(dòng)優(yōu)化與分析

從上圖可以看出,啟動(dòng)過(guò)程中,Cold的模式下,生命周期中做的事情最多,啟動(dòng)的時(shí)間最長(zhǎng),因此,我們以冷啟動(dòng)來(lái)衡量APP啟動(dòng)時(shí)間。啟動(dòng)過(guò)程中,如何判斷哪些生命周期影響啟動(dòng)速度呢?

3 啟動(dòng)過(guò)程

我們知道,APP的啟動(dòng)和運(yùn)行,就是Linux系統(tǒng)創(chuàng)建進(jìn)程和組件對(duì)象,并在UI線程中處理組件消息的過(guò)程。

啟動(dòng)過(guò)程圖:

愛(ài)奇藝Android客戶端啟動(dòng)優(yōu)化與分析

App的啟動(dòng)過(guò)程,可以劃分為三個(gè)階段:

3.1 創(chuàng)建進(jìn)程

當(dāng)APP啟動(dòng)時(shí),如果當(dāng)前app的進(jìn)程不存在,便會(huì)創(chuàng)建新的進(jìn)程;App主進(jìn)程啟動(dòng)后,如果啟動(dòng)某個(gè)組件,并且該組件設(shè)置了android:process屬性,組件所運(yùn)行的進(jìn)程不存在,也會(huì)創(chuàng)建新的進(jìn)程。

需要注意的是,如果在啟動(dòng)階段,初始化的組件中,包含了多個(gè)進(jìn)程,便會(huì)創(chuàng)建多次進(jìn)程,BindApplication操作也會(huì)重復(fù)執(zhí)行多次

3.2 創(chuàng)建UI線程及Handler

進(jìn)程創(chuàng)建后,會(huì)通過(guò)反射,執(zhí)行ActivityThread入口函數(shù),創(chuàng)建Handler,并在當(dāng)前線程中prepareMainLooper,并在Handler中接收組件的消息,我們來(lái)看一下Handler中處理的消息:

  • LAUNCH_ACTIVITY,啟動(dòng),執(zhí)行Activity
  • RESUME_ACTIVITY,恢復(fù)Activity
  • BIND_APPLICATION,啟動(dòng)app
  • BIND_SERVICE,Service創(chuàng)建, onBind
  • LOW_MEMORY,內(nèi)存不足,回收后臺(tái)程序

sMainThreadHandler中,處理的消息很多,這里只羅列了,可能在啟動(dòng)階段可能會(huì)執(zhí)行的操作, 這些操作都是運(yùn)行在Main Thread中,對(duì)啟動(dòng)而言,屬于阻塞性的。

Activity生命周期,自然需要在啟動(dòng)階段執(zhí)行,但,對(duì)于Service的創(chuàng)建,Trim_memory回調(diào),廣播接收等操作,就需要重點(diǎn)考慮,其操作耗時(shí)性。

3.3 Activity運(yùn)行及繪制

前兩個(gè)過(guò)程,創(chuàng)建進(jìn)程和UI線程及Handler,都是由系統(tǒng)決定的,對(duì)APP開(kāi)發(fā)者而言,并不能控制其執(zhí)行時(shí)間,在本階段,執(zhí)行BindApplication,和Acitivity生命周期,都是可以由開(kāi)發(fā)者自定義。

Activity執(zhí)行到onResume之后,會(huì)執(zhí)行至ViewRootImpl,執(zhí)行兩次performTraversals,第二次traversal操作中,會(huì)執(zhí)行performDraw操作,同時(shí)通知RenderThread線程執(zhí)行繪制.

從啟動(dòng)的三個(gè)階段,我們可以看出,啟動(dòng)啟動(dòng)時(shí)間的長(zhǎng)短,決定因素在于,主線程中所做事情消耗的時(shí)間的多少,所以,我們的優(yōu)化工作主要集中在,排查主線程中耗時(shí)性的工作,并進(jìn)行合理的優(yōu)化。Android手機(jī),系統(tǒng)的資源是有限的,過(guò)多的異步線程,會(huì)搶占CPU,導(dǎo)致主線程執(zhí)行時(shí)間片間隔增大。同樣的,內(nèi)存消耗狀態(tài),GC頻率,也會(huì)影響啟動(dòng)的時(shí)間。

4 分析及測(cè)量

通過(guò)上述的源碼的解讀,我們已經(jīng)了解了啟動(dòng)過(guò)程,以及可能引起啟動(dòng)過(guò)慢的原因。接下來(lái)介紹一些常用的分析手段及時(shí)間測(cè)量方法。

啟動(dòng)分析工具,主要使用SysTrace,具體的使用方法,請(qǐng)參考官網(wǎng)文檔https://developer.android.com/studio/command-line/systrace。

4.1 SysTrace分析技巧

4.1.1 UI Thread 顏色顯示

愛(ài)奇藝Android客戶端啟動(dòng)優(yōu)化與分析

  • 綠色:Running
  • 白色:Sleeping
  • 棕色:Uninterruptible Sleep
  • 橙色:Uninterruptible Sleep - Block I/O

其中10ms以內(nèi)的,較短時(shí)間的Sleeping狀態(tài),不用關(guān)注,可能是由于CPU調(diào)度的時(shí)間片分配間隔引起的;較長(zhǎng)時(shí)間的Block I/O和Sleep狀態(tài),可以確定有阻塞啟動(dòng)的邏輯在這個(gè)階段運(yùn)行,需要進(jìn)一步對(duì)代碼進(jìn)行分析定位。

4.1.2 查看CPU狀態(tài)及線程運(yùn)行時(shí)長(zhǎng)

查看CPU占用狀態(tài):

愛(ài)奇藝Android客戶端啟動(dòng)優(yōu)化與分析

線程執(zhí)行:

愛(ài)奇藝Android客戶端啟動(dòng)優(yōu)化與分析

通過(guò)該階段密集程度,反映出CPU占用率,也能在一定程度上反映出該階段執(zhí)行時(shí)間被阻塞情況;線程執(zhí)行情況統(tǒng)計(jì),可以查看線程執(zhí)行時(shí)間排名,對(duì)執(zhí)行時(shí)間較長(zhǎng)的子線程進(jìn)行優(yōu)化。

4.2 SysTrace啟動(dòng)時(shí)間

在SysTrace圖中,UI Thread中包含了bindApplication,activityStart,traversal等操作,RenderThread中包含DrawFrame等操作。這些TAG節(jié)點(diǎn)是源碼已經(jīng)添加的,可參考#3.2中介紹。

Trace上啟動(dòng)時(shí)間:從bindApplication至第二次traversal完成,可認(rèn)為UI***次繪制完成,啟動(dòng)完成。選中開(kāi)始點(diǎn)和結(jié)束點(diǎn),可以查看過(guò)程消耗的時(shí)間。

4.3 adb shell am start -W

在統(tǒng)計(jì)APP啟動(dòng)時(shí)間時(shí),系統(tǒng)為我們提供了adb命令,可以輸出啟動(dòng)時(shí)間

TotalTime: 表示新應(yīng)用啟動(dòng)的耗時(shí),包括新進(jìn)程的啟動(dòng)和 Activity 的啟動(dòng),但不包括前一個(gè)應(yīng)用 Activity pause 的耗時(shí)

系統(tǒng)在繪制完成后,ActivityManagerService會(huì)回調(diào)該方法,統(tǒng)計(jì)時(shí)間不如SysTrace準(zhǔn)確,但是能夠方便我們通過(guò)腳本多次啟動(dòng)測(cè)量TotalTime,對(duì)比版本間啟動(dòng)時(shí)間差異。

4.4 埋點(diǎn)

通過(guò)APP啟動(dòng)生命周期中,關(guān)鍵位置加入時(shí)間點(diǎn)記錄,達(dá)到測(cè)量目的。

4.5 錄屏

錄屏方式收集到的時(shí)間,更接近于用戶的真實(shí)體感。

5 優(yōu)化

為了讓用戶在進(jìn)入APP之后,更快更流暢的使用服務(wù),所以會(huì)在啟動(dòng)過(guò)程中,提前對(duì)一些基礎(chǔ)庫(kù)和組建進(jìn)行初始化操作,這就意味著系統(tǒng)有限的資源會(huì)被搶占,影響啟動(dòng)時(shí)間。啟動(dòng)時(shí)間的優(yōu)化,是一個(gè)平衡性能和體驗(yàn)的過(guò)程。

通過(guò)Systrace工具分析,我們發(fā)現(xiàn)愛(ài)奇藝愛(ài)奇藝安卓APP啟動(dòng)過(guò)程中一些問(wèn)題,接下來(lái),我們就結(jié)合具體的業(yè)務(wù)實(shí)踐,進(jìn)行啟動(dòng)問(wèn)題進(jìn)行優(yōu)化。

5.1 區(qū)分進(jìn)程初始化Application

由#3我們了解到,對(duì)于一個(gè)app而言,App內(nèi)組件可以運(yùn)行在不同的進(jìn)程之中。舉個(gè)例子: 一個(gè)APP擁有主進(jìn)程,插件進(jìn)程,下載進(jìn)程三個(gè)進(jìn)程,會(huì)在啟動(dòng)階段創(chuàng)建相應(yīng)的組件,但只有一個(gè)QYApplication繼承自系統(tǒng)Application,創(chuàng)建三次進(jìn)程,QYApplication中attach(),onCreate()方法都會(huì)被執(zhí)行三次。

每個(gè)進(jìn)程說(shuō)需要初始化的內(nèi)容肯定是不一樣的,所以,為了防止資源的浪費(fèi),我們需要區(qū)分進(jìn)程,初始化Appcation.

成果:對(duì)多進(jìn)程應(yīng)用而言,通過(guò)對(duì)初始化內(nèi)容進(jìn)行梳理,合理區(qū)分初始化,會(huì)大幅減少內(nèi)存和CPU占用。

5.2 異步處理耗時(shí)任務(wù)

子線程處理耗時(shí)任務(wù),主線程做的事情越少,越早進(jìn)入Acitivity繪制階段,界面越早展現(xiàn)。

注意:

  • 不在主線程做耗時(shí)任務(wù),如文件,網(wǎng)絡(luò)等
  • 啟動(dòng)階段初始化任務(wù),盡量在異步線程處理
  • 主線程,不用等待或者依賴于子線程任務(wù)

進(jìn)一步優(yōu)化:可以自建線程池,維持一定線程個(gè)數(shù),管理任務(wù)隊(duì)列。

5.3 防止多線程搶占CPU

Android系統(tǒng)資源有限,特別是CPU資源,理論上來(lái)說(shuō),UI線程執(zhí)行的任務(wù),也無(wú)法保證一直被調(diào)度狀態(tài),當(dāng)并發(fā)的線程數(shù)過(guò)多,UI線程時(shí)間片會(huì)更短,從而導(dǎo)致啟動(dòng)時(shí)間被變慢。

下面羅列一些常見(jiàn),容易造成CPU被搶占的場(chǎng)景:

愛(ài)奇藝Android客戶端啟動(dòng)優(yōu)化與分析

成果:通過(guò)對(duì)執(zhí)行時(shí)間較久,執(zhí)行頻率的業(yè)務(wù)進(jìn)行優(yōu)化,將CPU占有率維持在合理的程度,會(huì)大幅減少啟動(dòng)時(shí)間,減少300ms以上。

5.4 系統(tǒng)API使用

部分系統(tǒng)的API使用是阻塞性的,文件很小可能無(wú)法感知,當(dāng)文件過(guò)大,或者使用頻繁時(shí),可能造成阻塞。例如:

SharedPreference.Editor提交操作:

  • commit方法屬于屬于阻塞性質(zhì)API,建議使用apply。

此外,我們知道,SP文件的存儲(chǔ)是一個(gè)XML文件,以key-value形式存儲(chǔ),當(dāng)業(yè)務(wù)過(guò)多時(shí),需要拆分為多個(gè)文件存儲(chǔ),防止文件過(guò)大,出現(xiàn)讀取耗時(shí)及ANR。

進(jìn)一步優(yōu)化,可對(duì)啟動(dòng)階段,頻繁的SP操作在內(nèi)存中,統(tǒng)一提交。

AssetManager.open操作: Android開(kāi)發(fā)中,我們有時(shí)會(huì)將資源文件放在assets目錄中,然后使用open操作讀取文件,如果文件過(guò)大,需要在異步線程中執(zhí)行。

成果:隨著業(yè)務(wù)量日積月累,正常的系統(tǒng)API的使用,也可能出現(xiàn)問(wèn)題,通過(guò)排除,可減少50-100ms。

5.5 精簡(jiǎn)布局

布局的復(fù)雜程度,直接影響繪制的時(shí)間。

舉個(gè)例子,在啟動(dòng)過(guò)程中,會(huì)有需要大的背景圖,只有***次安裝時(shí)使用,后續(xù)屬性設(shè)置為android:visibility="gone",但是,雖然設(shè)置了gone屬性,不會(huì)顯示,但依舊會(huì)被解析。

建議:

減少布局層次

無(wú)用資源使用ViewStub,使用時(shí)加載

  1. 成果:?jiǎn)?dòng)階段的布局較簡(jiǎn)單,通過(guò)優(yōu)化背景圖片的加載,減少50-100ms。

5.6 Service延后初始化

App啟動(dòng)中過(guò)程中,經(jīng)常進(jìn)行Service初始化操作,由于Service使用一般不涉及界面,可能會(huì)認(rèn)為初始化生命周期不在主線程中,其實(shí)不然,在3.2的啟動(dòng)過(guò)程源碼介紹中講到,Service的生命周期,也屬于主線程Handler接收的Message之一。

  1. 建議:Service生命周期中,注意邏輯執(zhí)行時(shí)間性能優(yōu)化,初始化盡量延后。
  2. 成果:取決于初始化Service的生命周期執(zhí)行時(shí)間,可減少200ms以上。

5.7 將任務(wù)delay至首頁(yè)繪制完成后

對(duì)于APP首頁(yè)展示不需要的初始化邏輯,可延后至首頁(yè)繪制完成后初始化。

注意:

需要post兩次才能保證在***次繪制之后顯示,因?yàn)椋到y(tǒng)繪制會(huì)執(zhí)行兩次Performtraversal。

進(jìn)一步優(yōu)化:可將業(yè)務(wù)邏輯的初始化劃分為,首頁(yè)繪制后,5s,10s,20s三個(gè)階段分別初始化,防止首頁(yè)繪制執(zhí)行任務(wù)過(guò)多造成掉幀。

成果:釋放繪制階段的CPU,可將復(fù)雜的繪制提前200ms以上。

6 監(jiān)控

穩(wěn)定的用戶體驗(yàn)依賴于持續(xù)的監(jiān)控,愛(ài)奇藝為監(jiān)控啟動(dòng)性能建立了一套監(jiān)控體系,測(cè)試,工具,開(kāi)發(fā)等幾個(gè)團(tuán)隊(duì)從不同的緯度搭建不同的監(jiān)控方案

  1. 測(cè)試:錄屏,從用戶的真實(shí)體驗(yàn)角度,獲取最準(zhǔn)確的啟動(dòng)時(shí)間。
  2. 實(shí)時(shí)監(jiān)控:通過(guò)埋點(diǎn),大數(shù)據(jù)采樣投遞獲取真實(shí)線上環(huán)境數(shù)據(jù),從地域,時(shí)間,機(jī)型,app版本,系統(tǒng)版本等各個(gè)緯度對(duì)啟動(dòng)時(shí)間進(jìn)行監(jiān)控。
  3. 腳本測(cè)試:通過(guò)對(duì)腳本,對(duì)同一收集多次啟動(dòng)數(shù)據(jù)進(jìn)行收集,通過(guò)不同版本間的對(duì)比,監(jiān)控啟動(dòng)時(shí)間的變化情況。

7 SysTrace擴(kuò)展

SysTrace通過(guò)TAG節(jié)點(diǎn)可以清晰展現(xiàn),啟動(dòng)過(guò)程以及方法執(zhí)行時(shí)間,但是,從發(fā)現(xiàn)問(wèn)題,然后通過(guò)節(jié)點(diǎn)去定位問(wèn)題,是一件很繁瑣的工作,如果你們工程編譯又比較慢,簡(jiǎn)直讓人崩潰。

7.1 自動(dòng)化TAG注入

在Android工程編譯的過(guò)程中,指定class,在方法前后,自動(dòng)化插入Trace節(jié)點(diǎn),統(tǒng)計(jì)方法執(zhí)行時(shí)間。

流程:

  • 在編譯的過(guò)程中,插入自定義Task任務(wù),
  • 讀取配置文件,文件中包含了需要注入java文件名和路徑名和method
  • 找到需要注入的class文件,然后通過(guò)ASM改變字節(jié)碼,方法前后,插入自定義自定義方法

通過(guò)工具的操作,能夠做到不用修改原有工程文件,自動(dòng)在打包時(shí)注入TAG節(jié)點(diǎn)和邏輯代碼,配置文件可以循環(huán)利用,提高分析效率,節(jié)能環(huán)保。

8 優(yōu)化結(jié)果

啟動(dòng)時(shí)間,由于不同的機(jī)型性能同,Android系統(tǒng)版本不同,同一APP版本啟動(dòng)時(shí)間,相差很大,所以統(tǒng)計(jì)一般以同一手機(jī),不同版本做比較,盡量保證手機(jī)狀態(tài)一致。

SysTrace手機(jī)優(yōu)化時(shí)間對(duì)比:

愛(ài)奇藝Android客戶端啟動(dòng)優(yōu)化與分析

腳本多次啟動(dòng)時(shí)間收集對(duì)比:

愛(ài)奇藝Android客戶端啟動(dòng)優(yōu)化與分析

經(jīng)過(guò)多個(gè)版本的持續(xù)優(yōu)化,有無(wú)廣告兩種不同的場(chǎng)景下,啟動(dòng)時(shí)間分別減少40%和35%,啟動(dòng)速度得到了較大的提升。

9 總結(jié)

啟動(dòng)時(shí)間的優(yōu)化和監(jiān)控,是一項(xiàng)長(zhǎng)期的任務(wù),需要對(duì)異常的情況進(jìn)行分析,對(duì)可能造成阻塞的代碼邏輯進(jìn)行合理的優(yōu)化,非常感謝各個(gè)業(yè)務(wù)團(tuán)隊(duì)支持和配合。

責(zé)任編輯:未麗燕 來(lái)源: 安卓巴士
相關(guān)推薦

2022-06-10 15:37:24

愛(ài)奇藝App網(wǎng)絡(luò)

2023-08-11 07:44:09

大數(shù)據(jù)數(shù)據(jù)分析

2023-06-05 07:36:30

數(shù)據(jù)湖大數(shù)據(jù)架構(gòu)

2012-07-18 09:29:14

愛(ài)奇藝Windows Pho

2021-01-08 13:42:28

愛(ài)奇藝機(jī)器學(xué)習(xí)深度學(xué)習(xí)

2015-07-23 14:50:54

2011-10-31 13:42:46

Android客戶端人人網(wǎng)

2010-05-31 10:11:32

瘦客戶端

2015-07-22 12:53:55

羅生門(mén)式

2016-12-23 14:03:40

華為愛(ài)奇藝

2013-08-15 14:12:57

咪咕愛(ài)唱

2018-04-27 16:11:03

京東

2021-07-16 06:56:50

Nacos注冊(cè)源碼

2011-07-01 10:00:11

Ubuntu OneAndroid

2014-11-11 16:07:11

2015-07-07 12:03:01

2014-08-19 15:32:11

愛(ài)奇藝百加視頻手機(jī)

2020-02-17 19:48:15

超長(zhǎng)假服務(wù)器殺手

2015-07-16 16:22:41

愛(ài)奇藝
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)