系統(tǒng)啟動(dòng)過程:
1)開機(jī)打開電源
2)BootLoader程序
3)Linux的 init.rc
- init進(jìn)程
5)Zygote的JVM
6)SystemServer進(jìn)程
Binder線程池
SystemServiceManager(AMS桥氏、WMS、PMS择浊、CameraService等等被啟動(dòng))
1)啟動(dòng)頁白屏及黑屏解決?
2)啟動(dòng)太慢怎么解決媒至?
3)怎么保證應(yīng)用啟動(dòng)不卡頓齿坷?
4)App啟動(dòng)崩潰異常捕捉
5)統(tǒng)計(jì)啟動(dòng)時(shí)長(zhǎng),標(biāo)準(zhǔn)
App啟動(dòng)速度是用戶的第一印象,本章會(huì)介紹精準(zhǔn)度量啟動(dòng)速度的方式五垮,啟動(dòng)優(yōu)化的相關(guān)工具睬棚、常規(guī)優(yōu)化手段等第煮,同時(shí)我會(huì)介紹異步初始化以及延遲初始化的最優(yōu)解,以最優(yōu)雅抑党、可維護(hù)性高的的方式獲得閃電般的啟動(dòng)速度包警。...
一. App 啟動(dòng)優(yōu)化介紹
App Startup time
冷啟動(dòng):耗時(shí)最多、衡量標(biāo)準(zhǔn)底靠。
啟動(dòng)App害晦、加載空白Window、創(chuàng)建進(jìn)程
隨后任務(wù)苛骨,創(chuàng)建Application篱瞎、啟動(dòng)主線程、創(chuàng)建MainActivity痒芝。
熱啟動(dòng):后臺(tái) ——> 前臺(tái)俐筋。最快
溫啟動(dòng):較快。僅僅重走LifeCycle严衬。
優(yōu)化方向:
Application和Activity生命周期
二. 啟動(dòng)時(shí)間測(cè)量方式
兩種方式:adb 命令 / 手動(dòng)打點(diǎn)
adb方式
adb shell am start -W packagename/首屏Activity
ThisTime:最后一個(gè)Activity啟動(dòng)耗時(shí)
TotalTime:所有Activity啟動(dòng)耗時(shí)
WaitTime:AMS啟動(dòng)Activity的總耗時(shí)
(此方式線下使用方便澄者,不能帶到線上。非嚴(yán)謹(jǐn)、精確時(shí)間)手動(dòng)打點(diǎn):
啟動(dòng)時(shí)埋點(diǎn)粱挡,啟動(dòng)結(jié)束時(shí)埋點(diǎn)赠幕,兩者差值。
寫個(gè)工具類询筏,讀取SystemCurrentTimeMillis
結(jié)束時(shí)間的記錄位置榕堰?真實(shí)數(shù)據(jù)展示出來,F(xiàn)eed第一條展示嫌套。
onWindowFocusChanged不夠準(zhǔn)確逆屡。
getViewTreeObserver 的 addOnPreDrawListener
三. 啟動(dòng)優(yōu)化工具選擇
主要兩個(gè)工具:TraceView、Systrace
1. TraceView
圖形的形式展現(xiàn)執(zhí)行時(shí)間踱讨、調(diào)用等魏蔗。信息全面,包含所有線程
使用方式:Debug.startMethodTracing("");
Debug.stopMethodTracing("");
生成文件在sd卡:Android/data/packagename/files
最大能有 8MB的信息痹筛。
圖像分析:
Top Down:Self Time莺治、Total Time (Wall Clock Time、Thread Time)是call Chart 的詳細(xì)文字版本
Call Chart:a調(diào)用b帚稠,那么a 就在 b 的上面谣旁。系統(tǒng)API 橙色、應(yīng)用自己的綠色翁锡,第三放的就是藍(lán)色
Flame Chart:相同調(diào)用順序的過程會(huì)合并在一起蔓挖。
BottomUp:和Top Down相反。
TraceView 運(yùn)行時(shí)開銷嚴(yán)重馆衔,整體都會(huì)變慢。
與CpuProfiler相比怨绣,此工具Android Studio中直接使用角溃。可能需要手速很快才能獲取到篮撑。
2.Systrace
結(jié)合Android 內(nèi)核的數(shù)據(jù)减细,生成一個(gè)Html報(bào)告
API 18 以上使用,推薦TraceCompact
使用方式:
python systrace.py -t 10 [other-options] [categories]
https://developer.android.com/studio/command-line/systrace#command_options
查看CPU 核心運(yùn)行狀況
UIThread 和 Other Threads的對(duì)比
通過Slice 查看 start 赢笨、wall Duration(代碼執(zhí)行時(shí)間)未蝌、CPU Duration (代碼消耗cpu的時(shí)間)
舉例:鎖沖突
四. 優(yōu)雅獲取方法耗時(shí)講解
常規(guī)方法的侵入性太強(qiáng)。重復(fù)編輯茧妒。
所以萧吠,采用AOP方法(Aspect Oriented Programming 面向切面編程)
- 針對(duì)同一類問題的統(tǒng)一處理
- 無侵入添加代碼
AspectJ使用:
classPath ‘com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.0’
implementation 'org.aspectj:aspectjrt:1.8.+'
apply plugin: 'android-aspectjx'
Join Points:程序運(yùn)行時(shí)的執(zhí)行點(diǎn),可以作為切面的地方桐筏。
- 函數(shù)調(diào)用纸型、執(zhí)行
- 獲取、設(shè)置變量
- 類初始化
PointCut:帶條件的JoinPoints (篩選一下某些點(diǎn))
一種Hook,要插入代碼的位置
Before:PointCut之前執(zhí)行狰腌。Advice除破,具體插入位置。
After:PointCut之后執(zhí)行
Around:PointCut之前和之后分別執(zhí)行
execution:處理Join Point 的類型琼腔,call瑰枫、execution
(* android.app.Activity.on**(..)):匹配規(guī)則
onActivityCalled:要插入的代碼
4.1優(yōu)雅獲取方法耗時(shí)實(shí)操
4.2 異步優(yōu)化詳解
優(yōu)化技巧:
Theme切換:感覺上的快。
異步優(yōu)化:
子線程分擔(dān)住線程任務(wù)丹莲,并行減少時(shí)間光坝。
ExecutorService service = Executors.newFixedThreadPool(CORE_POOL_SIZE);
service.submit(new Runnable(){
public void run(){
方法分別放入;
}
});
不符合異步要求的圾笨。部分代碼必須運(yùn)行在主線程當(dāng)中教馆,那么放棄這種異步優(yōu)化的方案。
需要在某階段完成擂达。由于異步執(zhí)行不知道 子任務(wù)何時(shí)結(jié)束钻趋,跳轉(zhuǎn)新界面時(shí) 該方法是否完成弯蚜,
添加
private CountDownLatch mCountDownLatch = new CountDownLatch(1); // 一個(gè)簡(jiǎn)單的開/關(guān)鎖存器
在條件被滿足后
mCountDownLatch.countDown();
try {
mCountDownLatch.await();
} catch(InterruptedException e){
e.printStackTrace;
}
4.3 異步初始化最優(yōu)解-啟動(dòng)器-1
充分利用CPU多核,自動(dòng)梳理執(zhí)行順序
- 代碼Task化,啟動(dòng)邏輯抽象為Task溜哮。
- 根據(jù)所有任務(wù)以來關(guān)系排序生成一個(gè)有向無環(huán)圖
- 多線程按照排序后的優(yōu)先級(jí)依次執(zhí)行
4.4 異步初始化最優(yōu)解-啟動(dòng)器-2
TaskDispatcher。并向當(dāng)中要執(zhí)行的Task 分別繼承漆魔,在run方法中進(jìn)行執(zhí)行硝全。
4.5 更優(yōu)秀的延遲初始化方案
常規(guī)方式,回調(diào)方法中執(zhí)行耗時(shí)抄腔。很有可能導(dǎo)致feed 卡頓瓢湃。
對(duì)延遲任務(wù)進(jìn)行分批初始化。
- 利用IdleHandler特性赫蛇,空閑時(shí)執(zhí)行
4.6 啟動(dòng)優(yōu)化其它方案
異步绵患、延遲、懶加載悟耘。
技術(shù)落蝙、業(yè)務(wù)相結(jié)合。
cpu time才是優(yōu)化方向
按照systrace 及 cpu time 跑滿cpu
IO密集型 和 CPU密集型 操作暂幼。
收斂啟動(dòng)代碼修改權(quán)限筏勒。
結(jié)合Ci修改啟動(dòng)代碼需要Review通知
其他方案:
- 提前加載SharedPreferences。getSharedPreference load到內(nèi)存中旺嬉。如果沒有完成一直阻塞進(jìn)行等待管行。
- Multidex之前加載,利用此階段CPU覆寫 getApplicationContext() 返回 this鹰服。 attachBaseContext中
啟動(dòng)階段不啟動(dòng)子進(jìn)程病瞳,子進(jìn)程會(huì)共享CPU資源揽咕,導(dǎo)致主進(jìn)程CPU緊張。注意啟動(dòng)順序:App onCreate 之前是ContentProvider
類加載優(yōu)化:提前異步加載(可以替換掉系統(tǒng)的ClassLoader套菜,每個(gè)類加載的時(shí)候都打印一個(gè)Log)Class.forName() 只加載類本身及其靜態(tài)變量的引用類亲善。
new 類實(shí)例 可以額外加載類成員變量的引用類
啟動(dòng)階段抑制GC
- CPU鎖頻
啟動(dòng)速度模擬面試
1)你做啟動(dòng)優(yōu)化是怎么做的?
- 分析現(xiàn)狀逗柴、確認(rèn)問題蛹头。(目前啟動(dòng)流程復(fù)雜,主線程執(zhí)行了太多的代碼)
- 針對(duì)性優(yōu)化(實(shí)現(xiàn)異步初始化)簡(jiǎn)單異步 指向了啟動(dòng)器戏溺。
- 長(zhǎng)期保持優(yōu)化效果渣蜗。
2)是怎么異步的,異步遇到問題沒有旷祸?
- 異步演進(jìn)過程
- 詳細(xì)介紹啟動(dòng)器
3)有哪些容易忽略的點(diǎn)耕拷?
- cpu time 和 wall time。
- 注意延遲初始化的優(yōu)化
- 介紹黑科技托享,類加載骚烧。Systrace 可能沒有給滿的CPU,拉高CPU闰围。
4)版本迭代導(dǎo)致的啟動(dòng)變慢有好的解決方式嗎赃绊?
- 啟動(dòng)器
- 結(jié)合CI
- 監(jiān)控完善