1. 工具選擇
CPU Profiler、Systrace、StrictMode
原因復(fù)雜:代碼、內(nèi)存、繪制、IO均有可能導(dǎo)致卡頓。難以定位。
不易復(fù)現(xiàn):當(dāng)時(shí)場(chǎng)景強(qiáng)相關(guān)。
CPU Profiler:圖形的形式展示執(zhí)行時(shí)間、調(diào)用棧等。信息全面,包含所有線程。整體會(huì)變慢。
使用方式:
Debug.startMethodTracing("");
Debug.stopMethodTracing("");
生成文件在SD卡:Android/data/packagename/files
Systrace:監(jiān)控和跟蹤Api調(diào)用、線程運(yùn)行情況,生成Html報(bào)告
API 18以上使用,推薦TraceCompat
python systrace.py -t 10 [other-options] [categories]
https://developer.android.com/studio/command-line/systrace#command_options
優(yōu)點(diǎn):輕量級(jí)、開銷小。直觀反映CPU利用率。給出建議(Alert)
StrictMode:嚴(yán)苛模式,Android提供的一種運(yùn)行時(shí)檢測(cè)機(jī)制。方便強(qiáng)大,容易被忽視。
包含:線程策略和虛擬機(jī)策略檢測(cè)。
線程策略:自定義的耗時(shí)調(diào)用,detectCustomSlowCalls()
磁盤讀取操作,detectDiskReads
網(wǎng)絡(luò)請(qǐng)求操作
虛擬機(jī)策略:
Activity泄漏,detectActivityLeaks()
Sqlite泄漏,detecteLeakedSqliteObjects
檢測(cè)實(shí)例數(shù)量,setClassInstanceLimit()
2. 自動(dòng)化卡頓檢測(cè)方案及優(yōu)化
原理:一個(gè)線程只有一個(gè)Looper
mLogging對(duì)象在每個(gè)message處理前后被調(diào)用
主線程發(fā)生卡頓,是在dispatchMessage執(zhí)行耗時(shí)操作
具體實(shí)現(xiàn):
1)Looper.getMainLooper().setMessageLogging();
2)匹配>>>>>Dispatching,閾值時(shí)間后執(zhí)行任務(wù)(獲取堆棧)
3)匹配<<<<<Finished,任務(wù)啟動(dòng)之前取消掉
AndroidPermormanceMonitor實(shí)戰(zhàn)(blockcanary)
非侵入性的性能監(jiān)控組件,通知形式彈出卡頓信息
問題及優(yōu)化
卡頓了,但卡頓堆棧可能不準(zhǔn)確。和OOM一樣,最后的堆棧只是表象,不是真正的問題。
優(yōu)化:獲取監(jiān)控周期內(nèi)的多個(gè)堆棧,而不僅是最后一個(gè)。
startMonitor -> 高頻采集堆棧-> endMonitor -> 記錄多個(gè)堆棧 -> 上報(bào)
海量卡頓堆棧處理
高頻卡頓上報(bào)量太大,服務(wù)端有壓力。
分析:一個(gè)卡頓下多個(gè)堆棧大概率有重復(fù)
解決:對(duì)一個(gè)卡頓下堆棧進(jìn)行hash排重,找出重復(fù)的堆棧。
效果:極大的減少展示量且找到真正發(fā)生問題的堆棧。
3. ANR分析與實(shí)戰(zhàn)
KeyDispatchTimeout:5s
BroadcastTimeout:前臺(tái)10s,后臺(tái)60s
ServiceTimeout:前臺(tái)20s,后臺(tái)200s
ANR執(zhí)行流程:發(fā)生ANR,進(jìn)程接收異常終止信號(hào),開始寫入進(jìn)程ANR信息。
彈出ANR提示框(ROM表現(xiàn)不一)
ANR解決套路:
adb pull data/anr/traces.txt
存儲(chǔ)路徑。 根據(jù)此路徑來判斷是否ANR
詳細(xì)分析:cpu/io
線上ANR監(jiān)控方案
通過FileObserver 監(jiān)控文件變化,高版本會(huì)有權(quán)限問題
ANR-WatchDog
非侵入式ANR監(jiān)控組件
com.github.anrwatchdog:anrwatchdog:1.3.0
https://github.com/SalomonBrys/ANR-WatchDog
原理:
start -> post消息改值(主線程+1操作) -> 線程sleep
檢測(cè)值是否被修改 ->判斷ANR發(fā)生(沒有被修改 message沒有到即發(fā)生)
彌補(bǔ)高版本沒有權(quán)限讀取Trace.txt 的問題。結(jié)合使用
和BlockCanary區(qū)別:
BlockCanary監(jiān)控Msg。適合監(jiān)控卡頓。
ANR-WatchDog:看最終結(jié)果。適合補(bǔ)充ANR監(jiān)控。
3. 卡頓單點(diǎn)問題檢測(cè)方案
自動(dòng)化卡頓檢測(cè)方案并不夠。很多操作的耗時(shí)并沒有達(dá)到卡頓閾值,感受同樣不佳但是不會(huì)拋出異常堆棧信息。
體系化解決方案務(wù)必盡早暴露問題。
單點(diǎn)問題:主線程IPC、DB IO、View繪制操作
IPC問題監(jiān)測(cè):
監(jiān)測(cè)指標(biāo):IPC調(diào)用類型
調(diào)用耗時(shí)、次數(shù)
調(diào)用堆棧、發(fā)生線程。
常規(guī)方案:
IPC前后加埋點(diǎn)。不夠優(yōu)雅,容易忘記。維護(hù)成本大。
adb命令:
adb shell am trace-ipc start // 監(jiān)控的開始
adb shell am trace-ipc stop --dump-file /data/local/tmp/ipc-trace.txt
//結(jié)束,存放信息
adb pull /data/local/tmp/ipc-trace.txt // 導(dǎo)出
優(yōu)雅方案:
ARTHook
還是 AspectJ
?
ARTHook 可以Hook系統(tǒng)方法。ASpectJ針對(duì)非系統(tǒng)方法。
IPC場(chǎng)景:PackageManger得到應(yīng)用信息、get到設(shè)備的ID、AMS等等。
固定的調(diào)用方式,最后會(huì)調(diào)用到 “android.os.BinderProxy” transact方法
4. 如何實(shí)現(xiàn)界面秒開
首先通過Systrace(查看是否跑滿CPU),優(yōu)雅異步 + 優(yōu)雅延遲初始化。
異步Inflate、X2C、繪制優(yōu)化
提前獲取頁面數(shù)據(jù)
界面秒開率統(tǒng)計(jì):
onCreate 到 onWindowFocusChanged
特定接口適配Activity
Lancet:輕量級(jí) AOP框架
編譯速度快,支持增量編譯
API簡(jiǎn)單,沒有任何多余代碼插入 apk
@Proxy 通常用與對(duì)系統(tǒng)API調(diào)用的Hook
@Insert 常用于操作 App與library的類
界面秒開監(jiān)控維度
1)onCreate到onWindowFocusChanged 兩方法調(diào)用的時(shí)間間隔。
總體耗時(shí)。
2)生命周期的耗時(shí)。
3)生命周期間隔的耗時(shí)
5. 優(yōu)雅監(jiān)控耗時(shí)盲區(qū)
生命周期間隔
onResume到Feed展示的間隔
舉例:postMessage,很有可能在Feed之前執(zhí)行
TraceView
特別適合一段時(shí)間內(nèi)的盲區(qū)監(jiān)控
線程具體時(shí)間做了什么,一目了然。
TraceView適合現(xiàn)在,可以監(jiān)控系統(tǒng)Msg。
動(dòng)態(tài)替換適合線上,只有應(yīng)用自身的Msg
線上方案:
所有方法都是Msg,mLogging?沒有Msg具體堆棧
AOP切Handler方法?不清楚準(zhǔn)確執(zhí)行時(shí)間
使用統(tǒng)一的Handler:定制具體方法
定制gradle插件,編譯器動(dòng)態(tài)替換。
6. 卡頓優(yōu)化技巧總結(jié)初步
耗時(shí)操作:異步、延遲
布局優(yōu)化:異步Inflate、X2C、重繪解決
內(nèi)存:降低內(nèi)存占用,減少GC時(shí)間。
Log / TraceView的HeapTaskDesk
卡頓優(yōu)化工具建設(shè)
Systrace:看出CPU使用情況
TraceView:看出線程在特定時(shí)間做什么。相對(duì)開銷比較大。
StrictMode也是很強(qiáng)大的
自動(dòng)化監(jiān)控工具建設(shè)。
Android Performance monitor。ANR - WatchDog
高頻采集,找出重復(fù)率高的堆棧。
卡頓監(jiān)控工具
單點(diǎn)問題:AOP、Hook
盲區(qū)監(jiān)控:gradle 編譯器替換。監(jiān)控所有主線程msg執(zhí)行耗時(shí),以及調(diào)用堆棧 superHandler。
通過注解調(diào)整所有Handler的父類。
卡頓監(jiān)控指標(biāo):
卡頓率、ANR率、界面秒開時(shí)間
交互時(shí)間、生命周期時(shí)間
上報(bào)環(huán)境、場(chǎng)景信息!
7. 卡頓優(yōu)化模擬面試
1)你是怎么做卡頓優(yōu)化的?
體現(xiàn)出來不同階段的進(jìn)步,結(jié)構(gòu)化思維。
經(jīng)歷了一些階段,第一階段:系統(tǒng)工具定位、解決。
第二階段:自動(dòng)化卡頓方案及優(yōu)化。
第三階段:線上卡頓及線下監(jiān)測(cè)工具建設(shè)。
2)你是怎么自動(dòng)化的獲取卡頓信息的?
mLogging.println
不一定準(zhǔn)確。可以高頻采集,找出重復(fù)堆棧!
3)卡頓的一整套解決方案是怎么做的?
線下(盡量早)、線上(全面自動(dòng)化、異常感知靈敏度)工具相結(jié)合的方式
特定難點(diǎn)突破:?jiǎn)吸c(diǎn)問題、盲區(qū)監(jiān)控
SuperHandler