使用Systrace
須要開發者對於整個渲染的原理有較深的理解,而TraceView
則更爲直觀,你能夠經過它來分析在一段時間應用內各個線程的運行狀況,它會幫你計算出每一個方法的具體耗時,這樣咱們就能夠了解到方法運行的效率,定位到當前性能的瓶頸在哪,從而考慮將一些耗時的操做放在子線程中進行,或者延後執行來優化應用的啓動速度和解決卡頓問題。 和以前同樣,咱們分幾個部分介紹它:android
TraceView
的分析報表*.trace
報表Android Studio
中的Tools/Android/Android Device Monitor
,打開調試界面。Start Method Profiling
按鈕,以後就會開始跟蹤:
Stop Method Profiling
,等待一會,就會在右邊的窗口生成分析的報表,將鼠標上移到紅框的文件名處,能夠看到保存的位置,咱們能夠把它保存起來以便以後分析跟蹤問題:
*.trace
報表獲取完報表以後,咱們就能夠經過它來分析,這個區域分爲三個部分: bash
前面兩個區域都比較好理解,咱們主要看一下紫色區域的每一列具體的含義: ide
上面的表格中,一部分單位是百分比,另外一部分是ms
,要注意區別,除此以外,有兩點須要解釋一下:函數
Incl
和Excl
的概念 關於Incl
和Excl
的概念能夠用下面這段代碼來表示:public static void inclExcl(Context context) { //這個函數的運行時間爲 Incl Real Time
//假如這裏沒有調用任何函數,那麼這裏的運行時間就是:Excl Real Time
writeSomething(context, 1000); //這裏的運行時間是:Incl Real Time - Excl Real Time
}
複製代碼
Cpu Time
和Real 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
: 因爲咱們的界面須要等到onCreate
、onResume
等函數執行完以後,纔會真正的顯示出來,所以,咱們須要保證它們可以儘快地執行完,也就是它的Incl Real Time
儘量地短: 例以下面兩點是最基本的:
onCreate
:
onResume
:
咱們分析一下在啓動過程當中,因爲佈局複雜或者耗時操做致使的問題: 首先咱們看一下正常的狀況:
callActivityOnCreate
部分耗時爲6.180ms
callActivityOnResume
耗時爲1.219ms
咱們修改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
:
首先把佈局恢復成沒有問題的狀態,而後在onCreate
和onResume
方法中增長不一樣的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
耗時:
能夠看到,因爲咱們是另起了一個線程進行操做,所以,並不會佔用它的運行時間。經過TraceView
,咱們能夠了解到某些關鍵函數上的運行時間,正如前面第三點談到的,根據不一樣的狀況進行分析和優化,將會有效地提升應用的啓動速度,避免出現卡頓現象。