使用TraceView工具(Device Monitor)分析項目卡頓

介紹:

TraceView工具能做什么?

從代碼層面分析性能問題,針對每個方法來分析,比如當我們發現我們的應用出現卡頓的時候,我們可以來分析出現卡頓時在方法的調用上有沒有很耗時的操作,關注以下兩個問題:

  • 調用次數不多,但是每一次執行都很耗時
  • 方法耗時不大,但是調用次數太多

前言:
有時候,當你寫完代碼之后,你發現它的運行速度,比你預想的要慢,這種情況經常會無緣無故地出現,你專注于采用某種方法編寫代碼,來解決特定的問題,但是很快你發現代碼的運行時間過長,遠遠超過你的預期

緩慢的函數執行通常是由于兩方面的問題造成的:

  1. 是執行速度很慢的函數,這種函數很容易被發現。你的某些函數所花費的時間,超過你的預期2倍、10倍,甚至50倍,這種問題容易解決。只要找到那些運行很慢的函數,查看代碼找到問題所在,然后想辦法解決就可以了。
  2. 是當你有數以千計的函數時,每個函數所用的時間都額外增加一毫秒,從而導致整個程序執行速度變慢數百毫秒,這種類型的問題很難跟蹤,而且更難以解決,因為通常你需要分析,每段執行代碼才能發現這些小問題,這最終會影響你的產品發布,進而影響公司業績
  3. 總之就是在執行某些函數時大量的占用CPU時間片 導致頁面卡頓 如果硬件設備性能不好的話 應用就直接掛掉

Android SDK有一些很不錯的工具,幫助你找到這些有問題的代碼部分,讓你能夠立即解決它們,讓我們來了解它們
案例:

public class MainActivity extends AppCompatActivity {
    Button btn_batching;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn_batching = (Button) findViewById(R.id.btn_batching);
        //計算斐波拉契列數
        btn_batching.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                computeFibonacci(40);
            }
        });
    }

    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);
        }
    }
}

上面是一個非常簡單的例子 通過點擊Button調用computeFibonacci()函數在遞歸調用 將項目運行起來 再打開Android Monitor 進行分析:



點擊Button后CPU使用頻率明顯上升 如果是一個死循環 那么應用很將快就掛掉 現在我們使用TraceView工具(Device Monitor)來分析下到底是什么情況
**打開Android Device Monitor **



啟動TraceView

點擊 start Method Profiling后就開始執行我們的APP操作 我這里只有一個Button 點擊后就執行computeFibonacci(40)



等待大概5秒就stop Method Profiling 就會生成一份分析文件

由上圖看到的有三個面板 且也很直觀的看到了方法執行過程的樹狀圖黑壓壓的一片 想都不用想肯定出問題了 先看看函數執行時間軸面板

滑動鼠輪進行放大

詳細信息面板:
  • Parents: 表示調用這個方法的方法 (MainActivtiy$.onClick 調用的)
  • Children:表示這個方法中調用的其他方法(調用了computeFibonacci(1))
  • Parents while recursive: 只有出現遞歸調用才會出現 表示遞歸調用時涉及的父函數
  • Children while recursive: 只有出現遞歸調用才會出現 表示遞歸調用時涉及的子函數
列名 作用
Name 該進程中所調用的函數名稱
Incl Cpu Time 函數占用的CPU時間,包含內部調用其它函數的CPU時間
Excl Cpu Time 函數占用的CPU時間,但不包含內部調用其它函數所占用的CPU時間
Incl Real Time 函數運行的真實時間(以毫秒為單位),內含調用其它函數所占用的真實時間
Excl Real Time 函數運行的真實時間(以毫秒為單位),不包含調用其它函數所占用的真實時間
Calls+Recur Calls/Total 函數被調用次數以及遞歸調用占總調用次數的百分比
Cpu Time/Call 函數調用CPU時間與調用次數的比(該函數平均執行時間)
Real Time/Call 同CPU Time/Call類似,只不過統計單位換成了真實時間

通過上圖就可以看出是MainActivtiy.computeFibonacci(1)這個函數執行的時候發生了遞歸調用導致占用CPU太多時間 找到該函數進行代碼優化:

//代碼優化前
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);
        }
    }
//代碼優化后
//將遞歸換為for循環 同時使用緩存 先將結果緩存起來
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;
    }

以上是針對算法的優化 如果項目代碼確實必須那樣寫的話 可以考慮使用分線程去執行 在運行項目后使用TraceView工具進行觀察 很明顯時間軸面板干凈多了:


最后:
在開發過程中,為了使項目跑的很順暢,所以我們要使用好各種工具 給大家推薦幾篇關于項目優化的文章:
使用Android Monitor分析項目查找內存泄漏
使用MAT (Memory Analyzer Tool)分析Andriod項目內存泄漏
Android 性能優化:使用 Lint 優化代碼、去除多余資源
leakcanary

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容