性能優(yōu)化工具(三)-TraceView

一、簡介

TraceView 是 Android SDK 中內(nèi)置的一個(gè)工具,它可以加載 trace 文件,用圖形的形式展示代碼的執(zhí)行時(shí)間、次數(shù)及調(diào)用棧,主要便于我們分析及優(yōu)化方法的執(zhí)行.

官方文檔對(duì)TraceView的說明講得非常簡單,僅供參考吧:https://developer.android.com/studio/profile/traceview

二、生成和分析traceView文件

方式1:使用代碼

在目標(biāo)代碼塊前后加 trace 針對(duì)具體代碼位置檢測(cè)

android.os.Debug.startMethodTracing()

// 目標(biāo)代碼塊

android.os.Debug.stopMethodTracing()

當(dāng)你調(diào)用開始代碼的時(shí)候,系統(tǒng)會(huì)生產(chǎn) trace 文件,并且產(chǎn)生追蹤數(shù)據(jù),當(dāng)你調(diào)用結(jié)束代碼時(shí),會(huì)將追蹤數(shù)據(jù)寫入到 trace 文件中: /sdcard/Android/data/包名/files/dmtrace.trace 文件

下一步使用 adb 命令將 trace 文件導(dǎo)出到電腦:

adb pull /sdcard/shixintrace.trace /tmp

使用代碼生成 trace 方式的好處是容易控制追蹤的開始和結(jié)束,缺點(diǎn)就是步驟稍微多了一點(diǎn)。

方式2: Android Studio 中 monitor 點(diǎn)擊鬧鐘按鈕

生成文件打開效果:

優(yōu)點(diǎn):矩形圖展示執(zhí)行時(shí)間和調(diào)用關(guān)系還是比較直觀的
缺點(diǎn):左上角可以切換線程,但是無法將多個(gè)線程在同一平面做直觀對(duì)比,稍微有點(diǎn)不方便。

方式3(推薦,本文主要使用的方式):DDMS

在 DDMS 中, 選中進(jìn)程, 點(diǎn)擊 Start Method Profiling,點(diǎn)擊后變灰色,叫Stop Method Profiling,再點(diǎn)擊結(jié)束獲取信息,生成trace文件。

生成文件效果:

上圖界面分兩部分, 上面是時(shí)間線面板, 下面是分析面板

<1>時(shí)間線面板 (Timeline Panel) 展示了不同線程的執(zhí)行時(shí)間

其中不同的顏色表示不同的方法
同一個(gè)顏色脈沖 bar越長,說明執(zhí)行時(shí)間越久,如圖中的主線程 main
顏色脈沖 bar 的高度表示 cpu 的利用率,高度越高表示 cpu 利用率越高
空白表示這個(gè)時(shí)間段內(nèi)沒有執(zhí)行內(nèi)容
黑塊表示系統(tǒng)空閑(system idle)

交互操作:
放大: 鼠標(biāo)選中線程的顏色部分, 水平拉動(dòng)可以放大圖
還原: 雙擊時(shí)間線面板右上角dual click位置
縮?。耗壳斑€不知道怎么縮小 - - |||

<2>分析面板 (Profile Panel) 展示了不同方法的執(zhí)行時(shí)間信息

函數(shù)調(diào)用關(guān)系
點(diǎn)一個(gè)方法后可以看到有兩部分,一個(gè)是 Parents,另一個(gè)是 Children。

關(guān)鍵指標(biāo)

列名 描述
Name 該線程運(yùn)行過程中所調(diào)用的函數(shù)名
Incl Cpu Time % 表示以時(shí)間百分比來統(tǒng)計(jì)的 Incl Cpu Time
Incl Cpu Time 某函數(shù)占用的 CPU 時(shí)間,包含內(nèi)部調(diào)用其它函數(shù)的 CPU 時(shí)間
Excl Cpu Time % 表示以時(shí)間百分比來統(tǒng)計(jì)的 Excl Cpu Time
Excl Cpu Time 某函數(shù)占用的 CPU 時(shí)間,但不含內(nèi)部調(diào)用其它函數(shù)所占用的 CPU 時(shí)間
Incl Real Time % 表示以時(shí)間百分比來統(tǒng)計(jì)的 Incl Real Time
Incl Real Time 某函數(shù)運(yùn)行的真實(shí)時(shí)間 (以毫秒為單位),內(nèi)含調(diào)用其它函數(shù)所占用的真實(shí)時(shí)間
Excl Real Time % 表示以時(shí)間百分比來統(tǒng)計(jì)的 Excl Real Time
Excl Real Time 某函數(shù)運(yùn)行的真實(shí)時(shí)間 (以毫秒為單位),不含調(diào)用其它函數(shù)所占用的真實(shí)時(shí)間
Call + Recur Calls / Total 某函數(shù)被調(diào)用次數(shù)以及遞歸調(diào)用占總調(diào)用次數(shù)的百分比
Cpu Time / Call 某函數(shù)調(diào)用 CPU 時(shí)間與調(diào)用次數(shù)的比。相當(dāng)于該函數(shù)平均執(zhí)行時(shí)間
Real Time / Call 同CPU Time/Call類似,只不過統(tǒng)計(jì)單位換成了真實(shí)時(shí)間

定位問題:

定位問題時(shí) TraceView 的使用方式:

1)從上半部分查看哪些線程執(zhí)行時(shí)間長?什么時(shí)候開始執(zhí)行?與主線程交錯(cuò)時(shí)間?
哪些方法的執(zhí)行需要花費(fèi)很長時(shí)間

2)點(diǎn)擊 TraceView 中的 Cpu Time/Call,按照占用 CPU 時(shí)間從高到低排序
哪些方法調(diào)用次數(shù)非常頻繁

3)點(diǎn)擊 TraceView 中的 Calls + Recur Calls/Total ,按照調(diào)用次數(shù)從高到底排序
排序后,然后逐個(gè)排查是否有項(xiàng)目代碼或者依賴庫代碼,有的話點(diǎn)擊查看詳情,查看是這個(gè)方法還是調(diào)用的子方法的問題,進(jìn)一步定位問題。

三、案例分析

案例:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                computeFibonacci(50);
            }
        });
    }

    public int computeFibonacci(int positionInFibSequence) {
        //0 1 1 2 3 5 8
        if (positionInFibSequence <= 2) {
            return 1;
        } else {
            return computeFibonacci(positionInFibSequence - 1)
                    + computeFibonacci(positionInFibSequence - 2);
        }
    }
}

通過點(diǎn)擊Button調(diào)用computeFibonacci()函數(shù)在遞歸調(diào)用 將項(xiàng)目運(yùn)行起來

啟動(dòng)TraceView:

生成分析文件

看看函數(shù)執(zhí)行時(shí)間軸面板

滑動(dòng)鼠輪進(jìn)行放大

詳細(xì)信息面板:

從而找到問題:computeFibonacci遞歸調(diào)用導(dǎo)致占用CPU太多時(shí)間

優(yōu)化:

    //代碼優(yōu)化前
    public int computeFibonacci(int positionInFibSequence) {
        //0 1 1 2 3 5 8
        if (positionInFibSequence <= 2) {
            return 1;
        } else {
            return computeFibonacci(positionInFibSequence - 1)
                    + computeFibonacci(positionInFibSequence - 2);
        }
    }

    //代碼優(yōu)化后
//將遞歸換為for循環(huán) 同時(shí)使用緩存 先將結(jié)果緩存起來
    public int computeFibonacci(int positionInFibSequence) {
        int prev=0;
        int current=1;
        int values;
        for(int i=0;i<positionInFibSequence;i++){
            values=prev+current;
            prev=current;
            current=values;
        }
        return current;
    }

在運(yùn)行項(xiàng)目后使用TraceView工具進(jìn)行觀察 很明顯時(shí)間軸面板干凈多了:

總結(jié):traceView主要作用是針對(duì)項(xiàng)目中具體方法的耗時(shí)進(jìn)行優(yōu)化分析,一般是集合systrace一起使用。systrace懷疑到具體耗時(shí)方法,然后通過traceView來確認(rèn)。

參考:

https://blog.csdn.net/u011240877/article/details/54347396
http://www.itdecent.cn/p/d3c03c291093

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請(qǐng)通過簡信或評(píng)論聯(lián)系作者。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容