點滴:Android 調試工具TraceView

Traceview是android平臺配備的一個很好的性能分析工具。它可以通過圖形化的方式讓我們瞭解我們要跟蹤的程序的性能,並且能具體到method。

Android 2.2以上(含2.2)可以在 DDMS中進行Traceview。
 1,在設備表中選中你想進行method trace的進程
 2,單擊Method Profiling按鈕開始method trace。該按鈕在窗口的左上方,它在"stop"按鈕的左方,"Device菜單的正下方"。
 3,method trace進行中
 4,單擊Method Profiling按鈕停止method trace。緊接着系統會自動彈出Traceview窗口來顯示剛纔的method trace結果。

Traceview界面比較複雜,其UI劃分爲上下兩個面板,即Timeline Panel(時間線面板)Profile Panel(分析面板)。圖1-4所示爲Timeline Panel界面:

1-4  Traceview Timeline Panel示意圖

1-4中的Timeline Panel又可細分爲左右兩個Pane

  • 左邊Pane顯示的是測試數據中所採集的線程信息。由圖1-4可知,本次測試數據採集了main線程,兩個Binder線程和其它系統輔助線程(例如GC線程等)的信息。
  • 右邊Pane所示爲時間線,時間線上是每個線程測試時間段內所涉及的函數調用信息。這些信息包括函數名、函數執行時間等。由圖1-4可知,main線程對應行的的內容非常豐富,而其他線程在這段時間內幹得工作則要少得多。
  • 另外,開發者可以在時間線Pane中移動時間線縱軸。縱軸上邊將顯示當前時間點中某線程正在執行的函數信息。

現在來看TraceviewProfile Panel界面,如圖1-5所示:

1-5  TraceviewProfile Panel界面

Profile PanelTraceview的核心界面,其內涵非常豐富。它主要展示了某個線程(先在Timeline Panel中選擇線程)中各個函數調用的情況,包括CPU使用時間、調用次數等信息。而這些信息正是查找hotspot的關鍵依據。所以,對開發者而言,一定要了解Profile Panel中各列的含義。筆者總結了其中幾個重要列的作用,如表1-1所示:

1-1  Profile Panel各列作用說明

列名

描述

Name

該線程運行過程中所調用的函數名

Incl Cpu Time

某函數佔用的CPU時間,包含內部調用其它函數的CPU時間

Excl Cpu Time

某函數佔用的CPU時間,但不含內部調用其它函數所佔用的CPU時間

Incl Real Time

某函數運行的真實時間(以毫秒爲單位),內含調用其它函數所佔用的真實時間

Excl Real Time

某函數運行的真實時間(以毫秒爲單位),不含調用其它函數所佔用的真實時間

Call+Recur Calls/Total

某函數被調用次數以及遞歸調用佔總調用次數的百分比

Cpu Time/Call

某函數調用CPU時間與調用次數的比。相當於該函數平均執行時間

Real Time/Call

CPU Time/Call類似,只不過統計單位換成了真實時間

另外,每一個Time列還對應有一個用時間百分比來統計的列(如Incl Cpu Time列對應還有一個列名爲Incl Cpu Time %的列,表示以時間百分比來統計的Incl Cpu Time)。

瞭解完TraceviewUI後,現在介紹如何利用Traceview來查找hotspot

一般而言,hotspot包括兩種類型的函數:

  • 一類是調用次數不多,但每次調用卻需要花費很長時間的函數。在示例代碼中,它就是hotspot 1。
  • 一類是那些自身佔用時間不長,但調用卻非常頻繁的函數。在示例代碼中,它就是hotspot 2。

首先,我們來查找hotspot 1

Profile Panel中,選擇按Cpu Time/Call進行降序排序(從上之下排列,每項的耗費時間由高到低),得到如圖1-6所示的結果:

1-6  CPU Time/Call降序排列數據

1-6中:

  • MainActivity.onCreate是應用程序中的函數,它耗時爲4618.684。然後,點擊MainActivity.onCreate項,得到箭頭所示的小圖。
  • 小圖中,Parents一行顯示的是MainActivity.onCreate的調用者,本例中它是performCreate函數。這部分代碼屬於Framework部分。Children行顯示的是MainActivity.onCreate調用的子函數。
  • 在MainActivity.onCreate調用的子函數中,我們發現getStringsToShow在Incl Cpu Time %一列中佔據了63.3%,它是onCreate子函數耗費時間最長的,而且Calls+Recur Calls/Total列顯示其調用次數爲1,即它僅僅被調用一次了。這個函數是應用程序實現的,所以極有可能是一個潛在的Hotspot。
  • 另外,由於筆者已經知道getStringsToShow是示例應用自己實現的函數,故在圖1-6的大圖中,可直接根據MainActivity.getStringsToShow花費了2921.913CPU時間這個信息來確定Hotspot就是它。

相對來說,類型1hotspot比較好找,步驟是先按降序對時間項進行排列(可以是時間百分比、真實時間或CPU時間),然後查找耗費時間最多的函數。一般而言,先應對應用程序自己實現的函數進行排查,Framework的函數也有可能是hotspot,但主因一般還是在應用本身(例如設置複雜的界面,導致對應XML解析非常慢)。

現在,我們來看如何查找類型2hotspot

點擊Call/Recur Calls/Total列頭,使之按降序排列。關注點放在那些調用頻繁並且佔用資源較多的函數。圖1-7爲降序排列的結果圖。

1-7類型2 Hotspot查找過程示意之一

1-7所示的運行最頻繁的幾個函數中,我們發現了幾個懷疑點,由圖中的12箭頭標示。

  • 結合代碼,箭頭1所指的函數在代碼中實際並不存在。這是因爲代碼中直接訪問了內部類的私有成員,導致java編譯器在編譯時自動生成了這個函數。這個函數的調用次數非常多。所以,爲了提高效率,我們可以修改內部類成員的訪問類型定義爲public。不過,該函數的Incl Cpu Time並不高,只有3.2%。
  • 同樣,箭頭2所指部分的函數調用次數也很多,達到了5888多次。不過它們佔用的時間百分比只有0.9%。

第一次查找的潛在點被排除後,繼續瀏覽數據,得到如圖1-8所示的結果。

1-8  類型2 Hotspot查找過程示意之二

在圖1-8中:

  • 紅框處有兩個重載的MyMD5.getHashString函數調用,它們各運行了368次,而且佔用的CPU時間百分比達到了31.8%和53.2%。很顯然,這2處調用就有優化的餘地,這就是我們所懷疑的hotspot2。

找到hotspot之後,開發者就需要結合代碼來進行對應的優化了。關於Java代碼優化,讀者可參考如下資料:http://developer.android.com/training/articles/perf-tips.html

總體而言,Hotspot的查找是一個細緻的工作,需要開發者對目標程序的代碼,以及Traceview工具都比較熟悉才行。

1.3  Traceview小結

Traceview工具是Android平臺應用程序性能分析的利器。不過它的UI還是有些複雜。並且使用時感覺流暢度不夠好。

Google官方關於Traceview的介紹可參考以下鏈接,不過其內容以及較久未更新了。http://developer.android.com/tools/debugging/debugging-tracing.html




發佈了5 篇原創文章 · 獲贊 1 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章