1.TraceView 是什么
TraceView 是AndroidSDK 中內(nèi)置的一個(gè)工具,它可以加載trace文件,用圖形的形式展示代碼的執(zhí)行時(shí)間、次數(shù)及調(diào)用棧,便于我們分析。
手機(jī)卡頓很多時(shí)候都是由于某個(gè)操作過(guò)于耗時(shí),在茫茫代碼中查找元兇未免太過(guò)痛苦,這時(shí)候就該體現(xiàn) TraceView 的價(jià)值了,通過(guò)traceview,可以知道時(shí)間都消耗在哪里了
生成 trace 文件有三種方法:
使用代碼
使用 Android Studio
使用 DDMS
這里我只分享下用DDMS生成
2、詳細(xì)操作步驟:
打開(kāi) Android Device Monitor,在 DDMS 中打開(kāi) trace 文件,DDMS 會(huì)啟動(dòng) TraceView 加載 trace 文件:
操作手機(jī)上出現(xiàn)問(wèn)題的地方
3、分析生成的數(shù)據(jù):
先分析上半部分
上半部分顯示了不同線程的執(zhí)行時(shí)間
每種顏色代表不同的函數(shù)和步驟,同一顏色的區(qū)域越大,就代表這個(gè)步驟運(yùn)行時(shí)間越長(zhǎng)
程序中每個(gè)線程調(diào)用方法的啟動(dòng)和停止時(shí)間
同一個(gè)顏色越長(zhǎng),說(shuō)明執(zhí)行時(shí)間越久,如圖中的主線程 main
空白表示這個(gè)時(shí)間段內(nèi)沒(méi)有執(zhí)行內(nèi)容
右上角顯示程序總共運(yùn)行了13400毫秒
縱軸
TraceView界面下方表格中縱軸就是每個(gè)方法,包括了JDK的,Android SDK的,也有native方法的,當(dāng)然最重要的就是app中你自己寫(xiě)的方法,有些Android系統(tǒng)的方法執(zhí)行時(shí)間很長(zhǎng),那么有很大的可能就是你app中調(diào)用這些方法過(guò)多導(dǎo)致的。
下半部分展示了不同方法的執(zhí)行時(shí)間信息,關(guān)鍵指標(biāo)有三個(gè):
Cpu Time/Call :該方法平均占用 CPU 的時(shí)間
Real Time/Call :平均執(zhí)行時(shí)間,包括切換、阻塞的時(shí)間,>= Cpu Time
Calls + Recur Calls/Total :調(diào)用、遞歸次數(shù)
每個(gè)方法前面都有一個(gè)數(shù)字,可能是全部方法按照Incl CPU Time 時(shí)間的排序序號(hào)(后面會(huì)講到)
點(diǎn)一個(gè)方法后可以看到有兩部分,一個(gè)是Parents,另一個(gè)是Children。
Parent表示調(diào)用這個(gè)方法的方法,可以叫做父方法
Children表示這個(gè)方法中調(diào)用的其他方法,可以叫做子方法
橫軸
inclusive:就是說(shuō)除統(tǒng)計(jì)函數(shù)本身運(yùn)行的時(shí)間外再加上調(diào)用子函數(shù)所運(yùn)行的時(shí)間
Exclusive:統(tǒng)計(jì)函數(shù)本身運(yùn)行的時(shí)間
1. Incl Cpu Time
Incl Cpu Time表示方法top執(zhí)行的總時(shí)間,假如說(shuō)方法top的執(zhí)行時(shí)間為10ms,方法a執(zhí)行了1ms,方法b執(zhí)行了2ms,方法c執(zhí)行了3ms,方法d執(zhí)行了4ms(這里是為了舉個(gè)栗子,實(shí)際情況中方法a、b、c、d的執(zhí)行總時(shí)間肯定比方法top的執(zhí)行總時(shí)間要小一點(diǎn))。
publicvoidtop()?{
a();
b();
c();
d();
}
2. Excl Cpu Time
理解了Incl Cpu Time以后就可以很好理解Excl Cpu Time了,還是上面top方法的栗子:
方法top 的 Incl Cpu Time 減去 方法a、b、c、d的Incl Cpu Time 的時(shí)間就是方法top的Excl Cpu Time 了
3. Incl Real Time
這個(gè)感覺(jué)和Incl Cpu Time 差不多,第7條會(huì)講到。
4. Excl Real Time
同上
5. Calls + Recur Calls / Total
這個(gè)指標(biāo)非常重要!
它表示這個(gè)方法執(zhí)行的次數(shù),這個(gè)指標(biāo)中有兩個(gè)值,一個(gè)Call表示這個(gè)方法調(diào)用的次數(shù),Recur Call表示遞歸調(diào)用次數(shù),看下圖:
我選中了一個(gè)方法,可以看到這個(gè)方法的Calls + Recur Calls值是1 + 17,表示這個(gè)方法調(diào)用了1次,遞歸調(diào)用17次
。
6. Cpu Time / Call
重點(diǎn)來(lái)了!!!!!!!!!!
這個(gè)指標(biāo)應(yīng)該說(shuō)是最重要的,從上圖可以看到,這個(gè)方法的調(diào)用次數(shù)為3次,而它的Incl Cpu Time為251.793ms,方法調(diào)用了3次,所以每一次的時(shí)間為83.913(也就是Cpu Time)
getView方法執(zhí)行時(shí)間很長(zhǎng),那么必然導(dǎo)致列表滑動(dòng)的時(shí)候產(chǎn)生卡頓現(xiàn)象,可以在getView方法的Children方法列表中找到耗時(shí)最長(zhǎng)的方法,分析出現(xiàn)問(wèn)題的原因:
是因?yàn)橛羞^(guò)多的計(jì)算?
還是因?yàn)橛凶x取SD卡的操作?
還是因?yàn)閍dapter中View太復(fù)雜了?
還是因?yàn)樾枰泻芏嗯袛啵O(shè)置View的顯示還是隱藏
還是因?yàn)槠渌颉?/p>
7. Real Time / Call
Real Time 和 Cpu Time 我現(xiàn)在還不太明白它們的區(qū)別,我的理解應(yīng)該是:
Cpu Time 應(yīng)該是某個(gè)方法占用CPU的時(shí)間
Real Time 應(yīng)該是這個(gè)方法的實(shí)際運(yùn)行時(shí)間
為什么它們會(huì)有區(qū)別呢?可能是因?yàn)镃PU的上下文切換、阻塞、GC等原因方法的實(shí)際執(zhí)行時(shí)間要比Cpu Time 要稍微長(zhǎng)一點(diǎn)。
下半部分展示了不同方法的執(zhí)行時(shí)間信息,關(guān)鍵指標(biāo)有三個(gè):
Cpu Time/Call :該方法平均占用 CPU 的時(shí)間
Real Time/Call :平均執(zhí)行時(shí)間,包括切換、阻塞的時(shí)間,>= Cpu Time
Calls + Recur Calls/Total :調(diào)用、遞歸次數(shù)
點(diǎn)擊下面的任意一個(gè)方法,可以看到它的詳細(xì)信息:
Parents:選中方法的調(diào)用處
Children:選中方法調(diào)用的方法
根據(jù) TraceView 顯示內(nèi)容定位問(wèn)題
定位問(wèn)題時(shí) TraceView 的使用方式:
從上半部分查看哪些線程執(zhí)行時(shí)間長(zhǎng)?什么時(shí)候開(kāi)始執(zhí)行?與主線程交錯(cuò)時(shí)間?
哪些方法的執(zhí)行需要花費(fèi)很長(zhǎng)時(shí)間
點(diǎn)擊 TraceView 中的 Cpu Time/Call,按照占用 CPU 時(shí)間從高到低排序
哪些方法調(diào)用次數(shù)非常頻繁
點(diǎn)擊 TraceView 中的 Calls + Recur Calls/Total ,按照調(diào)用次數(shù)從高到底排序
排序后,然后逐個(gè)排查是否有項(xiàng)目代碼或者依賴庫(kù)代碼,有的話點(diǎn)擊查看詳情,查看是這個(gè)方法還是調(diào)用的子方法的問(wèn)題,進(jìn)一步定位問(wèn)題。
實(shí)例:
可以看到項(xiàng)目中我們寫(xiě)的方法的耗時(shí),可以點(diǎn)進(jìn)去,看child,查找時(shí)間消耗去向
1)
經(jīng)由上圖可以發(fā)現(xiàn),HouseListTask的doInBackground方法的時(shí)間消耗在UtilsLog和解析上了
2)GetHouseTrueCountAsynTask的doInBackground方法的時(shí)間消耗在了HttpClient.execute上了
GetHouseTrueCountAsynTask的onPostExcute方法的時(shí)間消耗在cacheToDisk這個(gè)方法上
3)getview方法時(shí)間消耗在inflate方法上了