> 參考文章:?[Traceview Walkthrough](https://developer.android.com/intl/zh-cn/tools/performance/traceview/index.html)?
> [Android 編程下的 TraceView 簡介及其案例實戰](http://www.cnblogs.com/sunzn/p/3192231.html)?
> [正確使用Android性能分析工具——TraceView](http://blog.jobbole.com/78995/)?
> [Android內存使用分析和程序性能分析](http://liaohuqiu.net/cn/posts/memory-and-profile-analysis-in-android/)
# TraceView工具能做什么?
從代碼層面分析性能問題,針對每個方法來分析,比如當我們發現我們的應用出現卡頓的時候,我們可以來分析出現卡頓時在方法的調用上有沒有很耗時的操作,關注以下兩個問題:
* 調用次數不多,但是每一次執行都很耗時
* 方法耗時不大,但是調用次數太多
簡單一點來說就是我們能找到頻繁被調用的方法,也能找到執行非常耗時的方法,前者可能會造成Cpu頻繁調用,手機發燙的問題,后者就是卡頓的問題
# TraceView工具啟動
打開Monitor,點擊圖中的標注的按鈕,啟動追蹤:

# TraceView工具面板
打開App操作你的應用后,再次點擊的話就停止追蹤并且自動打開traceview分析面板:?
?
traceview的面板分上下兩個部分:
* 時間線面板以每個線程為一行,右邊是該線程在整個過程中方法執行的情況
* 分析面板是以表格的形式展示所有線程的方法的各項指標
## 時間線面板
?
左邊是線程信息,main線程就是Android應用的主線程,這個線程是都會有的,其他的線程可能因操作不同而發生改變.每個線程的右邊對應的是該線程中每個方法的執行信息,左邊為第一個方法執行開始,最右邊為最后一個方法執行結束,其中的每一個小立柱就代表一次方法的調用,你可以把鼠標放到立柱上,就會顯示該方法調用的詳細信息:?
?
你可以隨意滑動你的鼠標,滑倒哪里,左上角就會顯示該方法調用的信息。?
1.如果你想在分析面板中詳細查看該方法,可以雙擊該立柱,分析面板自動跳轉到該方法:?
?
2.放大某個區域?
剛打開的面板中,是我們采集信息的總覽,但是一些局部的細節我們看不太清,沒關系,該工具支持我們放大某個特殊的時間段:
?
如果想回到最初的狀態,雙擊時間線就可以。?
3.每一個方法的表示:?

可以看出來,每一個方法都是用一個`凹`型結構來表示,坐標的凸起部分表示方法的開始,右邊的凸起部分表示方法的結束,中間的直線表示方法的持續.
## 分析面板
面板列名含義如下:
| 名稱 | 意義 |
| --- | --- |
| Name | 方法的詳細信息,包括包名和參數信息 |
| Incl Cpu Time | Cpu執行該方法該方法及其子方法所花費的時間 |
| Incl Cpu Time % | Cpu執行該方法該方法及其子方法所花費占Cpu總執行時間的百分比 |
| Excl Cpu Time | Cpu執行該方法所話費的時間 |
| Excl Cpu Time % | Cpu執行該方法所話費的時間占Cpu總時間的百分比 |
| Incl Real Time | 該方法及其子方法執行所話費的實際時間,從執行該方法到結束一共花了多少時間 |
| Incl Real Time % | 上述時間占總的運行時間的百分比 |
| Excl Real Time % | 該方法自身的實際允許時間 |
| Excl Real Time | 上述時間占總的允許時間的百分比 |
| Calls+Recur | 調用次數+遞歸次數,只在方法中顯示,在子展開后的父類和子類方法這一欄被下面的數據代替 |
| Calls/Total | 調用次數和總次數的占比 |
| Cpu Time/Call | Cpu執行時間和調用次數的百分比,代表該函數消耗cpu的平均時間 |
| Real Time/Call | 實際時間于調用次數的百分比,該表該函數平均執行時間 |
你可以點擊某個函數展開更詳細的信息:?
?
展開后,大多數有以下兩個類別:
* Parents:調用該方法的父類方法
* Children:該方法調用的子類方法
如果該方法含有遞歸調用,可能還會多出兩個類別:
* Parents while recursive:遞歸調用時所涉及的父類方法
* Children while recursive:遞歸調用時所涉及的子類方法
首先我們來看當前方法的信息:
| 列 | 值 |
| --- | --- |
| Name | 24 android/widget/FrameLayout.draw(L android/graphics/Canvas;)V |
| Incl Cpu% | 20.9% |
| Incl Cpu Time | 375.201 |
| Excl Cpu Time % | 0.0% |
| Excl Cpu Time | 0.000 |
| Incl Real Time % | 1.1% |
| Incl Real Time | 580.668 |
| Excl Real Time % | 0.0% |
| Excl Real Time | 0.000 |
| Calls+Recur | 177+354 |
| Cpu Time/Call | 0.707 |
| Real Time/Call | 1.094 |
根據下圖中的toplevel可以看出總的cpu執行時間為1797.167ms,當前方法占用cpu的時間為375.201,375.201/1797.167=0.2087,和我們的Incl Cpu Time%是吻合的。當前方法消耗的時間為580.668,而toplevel的時間為53844.141ms,580.668/53844.141=1.07%,和Incl Real Time %也是吻合的。在來看調用次數為177,遞歸次數為354,和為177+354=531,375.201/531 = 0.7065和Cpu Time/Call也是吻合的,580.668/531=1.0935,和Real Time/Call一欄也是吻合的。?

### Parents
現在我們來看該方法的Parents一欄:?

| 列 | 值 |
| --- | --- |
| Name | 22 com/android/internal/policy/impl/PhoneWindow$DecorView.draw(Landroid/graphics/Canvas;)V |
| Incl Cpu% | 100% |
| Incl Cpu Time | 375.201 |
| Excl Cpu Time % | 無 |
| Excl Cpu Time | 無 |
| Incl Real Time % | 100% |
| Incl Real Time | 580.668 |
| Excl Real Time % | 無 |
| Excl Real Time | 無 |
| Call/Total | 177/531 |
| Cpu Time/Call | 無 |
| Real Time/Call | 無 |
其中的Incl Cpu Time%變成了100%,因為在這個地方,總時間為當前方法的執行時間,這個時候的Incl Cpu Time%只是計算該方法調用的總時間中被各父類方法調用的時間占比,比如Parents有2個父類方法,那就能看出每個父類方法調用該方法的時間分布。因為我們父類只有一個,所以肯定是100%,Incl Real Time一欄也是一樣的,重點是Call/Total,之前我們看當前方式時,這一欄的列名為Call+Recur,而現在變成了Call/Total,這個里面的數值變成了177/531,因為總次數為531次,父類調用了177次,其他531次是遞歸調用。這一數據能得到的信息是,當前方法被調用了多少次,其中有多少次是父類方法調用的。
### Children
?
可以看出來,我們的子類有2個,一個是自身,一個是`23android/view/View.draw(L android/graphics/Canvas;)V`,self代表自身方法中的語句執行情況,由上面可以看出來,該方法沒有多余語句,直接調用了其子類方法。另外一個子類方法,可以看出被當前方法調用了177次,但是該方法被其他方法調用過,因為他的總調用次數為892次,你可以點擊進入子類方法的詳細信息中。
### Parents while recursive
?
列舉了遞歸調用當前方法的父類方法,以及其遞歸次數的占比,猶豫我們當前的方法遞歸了354次,以上三個父類方法遞歸的次數分別為348+4+2 = 354次。
### Children while recursive
?
列舉了當遞歸調用時調用的子類方法。