<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          愛(ài)奇藝客戶端啟動(dòng)優(yōu)化與實(shí)戰(zhàn)

          共 5370字,需瀏覽 11分鐘

           ·

          2020-06-23 23:24

          點(diǎn)擊“開(kāi)發(fā)者技術(shù)前線”,選擇“星標(biāo)?”

          在看|星標(biāo)|留言,? 真愛(ài)

          轉(zhuǎn)載自公眾號(hào) :愛(ài)奇藝技術(shù)產(chǎn)品團(tuán)隊(duì)?

          加我微信(文章末尾)獲取收獲一份面試禮包

          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ò)程,一般可以分為以下三類(lèi):


          1b5cdb88aec3ba6090c059e0cbff327f.webp



          從上圖可以看出,啟動(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ò)程圖:


          767a08376acfe4b134fde78622eb1350.webp



          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è)量方法。


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


          4.1 SysTrace分析技巧


          4.1.1 UI Thread 顏色顯示


          f51a9e54b5c8ab9168afce11c3f5d731.webp


          • 綠色:Running

          • 白色:Sleeping

          • 棕色:Uninterruptible Sleep

          • 橙色:Uninterruptible Sleep - Block I/O


          其中10ms以?xún)?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):


          751ba61dba770ea55a5d748e414b9092.webp



          線程執(zhí)行:


          e018c0519375aac79c05076b3475b561.webp



          通過(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中介紹。


          I?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í)間


          I?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.


          I?成果:對(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ù),盡量在異步線程處理

          • 主線程,不用等待或者依賴(lài)于子線程任務(wù)


          I 進(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)景:


          a2979a45515cccd95a036c76d3e171ab.webp



          I?成果:通過(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提交操作:

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

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

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

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


          I?成果:隨著業(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í)加載


          I?成果:?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之一。


          建議:Service生命周期中,注意邏輯執(zhí)行時(shí)間性能優(yōu)化,初始化盡量延后。


          I?成果:取決于初始化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ò)多造成掉幀。


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

          6 監(jiān)控

          穩(wěn)定的用戶體驗(yàn)依賴(lài)于持續(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í)間。


          流程:

          • 1.在編譯的過(guò)程中,插入自定義Task任務(wù),

          • 2.讀取配置文件,文件中包含了需要注入java文件名和路徑名和method

          • 3.找到需要注入的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ì)比:


          46b266ccdca118a77be1d81b817b40c3.webp



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


          cff5791978cca0da86c30377bbdde97e.webp



          經(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ì)支持和配合。

          以上就是全部啟動(dòng)時(shí)間優(yōu)化相關(guān)的內(nèi)容,謝謝大家能夠閱讀到這里,如果有更好的建議,歡迎交流!


          ?

          福利時(shí)間:

          前線推出學(xué)習(xí)交流一定要備注:研究/工作方向+地點(diǎn)+學(xué)校/公司+昵稱(chēng)(如目標(biāo)大前端+上海+上交+卡卡),根據(jù)格式備注,可更快被通過(guò)且邀請(qǐng)進(jìn)群

          掃碼加我微信和大佬們零距離



          END



          開(kāi)發(fā)者技術(shù)前線?,匯集技術(shù)前線快訊和關(guān)注行業(yè)趨勢(shì),大廠干貨,是開(kāi)發(fā)者經(jīng)歷和成長(zhǎng)的優(yōu)秀指南。
          歷史閱讀


          螞蟻金服技術(shù)中臺(tái)架構(gòu)實(shí)踐
          支付寶海量支付背后的架構(gòu)揭秘!
          Android 11 Bata 正式發(fā)布!閑魚(yú)最新升級(jí)版 Flutter 技術(shù)電子書(shū)開(kāi)放下載
          支付寶 App 啟動(dòng)性能優(yōu)化


          e0d484f3525bcbee85045c94e3dfe276.webp在看點(diǎn)一下
          瀏覽 63
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  性免费网站 | 亚洲欧美在线成人电影 | 91精品国产综合久久久久久久 | 在线日韩在线 | 青草视频在线播放 |