性能優化工具知識梳理(1) TraceView

1、概述

使用Systrace須要開發者對於整個渲染的原理有較深的理解,而TraceView則更爲直觀,你能夠經過它來分析在一段時間應用內各個線程的運行狀況,它會幫你計算出每一個方法的具體耗時,這樣咱們就能夠了解到方法運行的效率,定位到當前性能的瓶頸在哪,從而考慮將一些耗時的操做放在子線程中進行,或者延後執行來優化應用的啓動速度和解決卡頓問題。 和以前同樣,咱們分幾個部分介紹它:android

  • 獲取TraceView的分析報表
  • 分析報表的格式
  • 具體案例

2、獲取*.trace報表

  • 第一步:點擊Android Studio中的Tools/Android/Android Device Monitor,打開調試界面。
  • 第二步:以下面截圖所示,選中要分析的應用包名,點擊Start Method Profiling按鈕,以後就會開始跟蹤:
  • 第三步:進入應用內進行操做,操做完畢後,再次點擊上面的按鈕Stop Method Profiling,等待一會,就會在右邊的窗口生成分析的報表,將鼠標上移到紅框的文件名處,能夠看到保存的位置,咱們能夠把它保存起來以便以後分析跟蹤問題:

3、分析*.trace報表

獲取完報表以後,咱們就能夠經過它來分析,這個區域分爲三個部分: bash

  • 紅色區域:列出了運行的各個線程。
  • 藍色區域:線程在一段時間內的運行狀況,咱們點擊有顏色的地方,就能夠定位到具體作了哪些操做。
  • 紫色區域:方法調用的具體狀況。

前面兩個區域都比較好理解,咱們主要看一下紫色區域的每一列具體的含義: ide

上面的表格中,一部分單位是百分比,另外一部分是ms,要注意區別,除此以外,有兩點須要解釋一下:函數

  • InclExcl的概念 關於InclExcl的概念能夠用下面這段代碼來表示:
public static void inclExcl(Context context) { //這個函數的運行時間爲 Incl Real Time
        //假如這裏沒有調用任何函數,那麼這裏的運行時間就是:Excl Real Time
        writeSomething(context, 1000); //這裏的運行時間是:Incl Real Time - Excl Real Time
    }
複製代碼
  • Cpu TimeReal Time的區別 Real Time表示的是一個函數從開始到運行時候所佔用的時間,而CPU Time則表示CPU執行這段函數所耗費的時間。 舉個例子,假如咱們一個函數doSomething()CPU執行它首先花了time1的時間,以後CPU被分配用去執行別的函數花了time2,執行完以後繼續回來執行doSomething(),花了time3的時間把它執行完,那麼doSomething()Real Time就等於time1 + time2 + time3,而Cpu Time則等於time1 + time3

咱們能夠經過點擊具體的列進行排序,在平時的分析中,咱們主要關注一下:佈局

  • CPU Time / Call較高 這一列表示函數的單個執行時間較長,這裏每每是能夠優化的點:性能

  • 分析該函數的實現方式,可以用其它的方法來實現,從而減小函數的運行時間優化

  • 分析該函數所執行的線程,若是能夠那麼把它放到子線程中執行動畫

  • 分析該函數所調用的時機,避免在應用啓動,或者作動畫的過程當中執行它,不然會致使啓動速度變慢和界面卡頓。ui

  • CPU Time較高,但CPU Time / Call不高 這一列表示函數的單個執行時長不長,但調用的次數不少,這一樣是能夠優化的點,須要看一下是否有必要在每一個地方都調用它,可否進行延後操做,統計到一個地方執行。this

  • Android相關的某些函數的Real Time: 因爲咱們的界面須要等到onCreateonResume等函數執行完以後,纔會真正的顯示出來,所以,咱們須要保證它們可以儘快地執行完,也就是它的Incl Real Time儘量地短: 例以下面兩點是最基本的:

  • onCreate

  • onResume

4、具體案例

咱們分析一下在啓動過程當中,因爲佈局複雜或者耗時操做致使的問題: 首先咱們看一下正常的狀況:

  • callActivityOnCreate部分耗時爲6.180ms
  • callActivityOnResume耗時爲1.219ms

4.1 佈局層次過於複雜致使的問題

咱們修改Activity的根佈局:

<FrameLayout
        android:background="@android:color/black"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <FrameLayout
            android:background="@android:drawable/screen_background_dark"
            android:layout_width="match_parent"
            android:layout_height="500dp">
            <FrameLayout
                android:background="@android:drawable/star_big_off"
                android:layout_width="match_parent"
                android:layout_height="400dp">
                <FrameLayout
                    android:background="@android:drawable/bottom_bar"
                    android:layout_width="match_parent"
                    android:layout_height="300dp">
                    <FrameLayout
                        android:background="@android:color/holo_blue_bright"
                        android:layout_width="match_parent"
                        android:layout_height="200dp">
                    </FrameLayout>
                </FrameLayout>
            </FrameLayout>
        </FrameLayout>
</FrameLayout>
複製代碼

再次抓取以後,看一下onCreate的時間,發現耗時增長到17ms

以後再點擊這個函數,分析裏面耗時最長的子方法,能夠看到就是因爲佈局引發的:

4.2 在啓動過程當中進行耗時的操做

首先把佈局恢復成沒有問題的狀態,而後在onCreateonResume方法中增長不一樣的IO操做:

public class TraceViewActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_trace_view);
        TraceViewOperation.writeOnActivityOnCreate(this, 1000);
    }

    @Override
    protected void onResume() {
        super.onResume();
        TraceViewOperation.writeOnActivityOnResume(this, 1000);
    }

}
複製代碼

其中onCreate在主線程中進行,而onResume裏面則另起了一個線程:

public class TraceViewOperation {

    public static void writeOnActivityOnCreate(Context context, int count) {
        writeSomething(context, count);
    }
    
    public static void writeOnActivityOnResume(final Context context, final int count) {
        new Thread() {
            @Override
            public void run() {
                super.run();
                writeSomething(context, count);
            }
        }.start();
    }

}
複製代碼
  • onCreate耗時:
    和上面相似,點進去看耗時的方法,正是因爲咱們在前面進行IO操做引發的:
  • onResume耗時:
    能夠看到,因爲咱們是另起了一個線程進行操做,所以,並不會佔用它的運行時間。

5、小結

經過TraceView,咱們能夠了解到某些關鍵函數上的運行時間,正如前面第三點談到的,根據不一樣的狀況進行分析和優化,將會有效地提升應用的啓動速度,避免出現卡頓現象。


更多文章,歡迎訪問個人 Android 知識梳理系列:

相關文章
相關標籤/搜索