日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

性能分析工具 Android TraceView

發布時間:2025/4/16 Android 68 豆豆
生活随笔 收集整理的這篇文章主要介紹了 性能分析工具 Android TraceView 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1. TraceView 簡介

Traceview是android平臺配備一個很好的性能分析的工具。它可以通過圖形化的方式讓我們了解我們要跟蹤的程序的性能,并且能具體到每個方法的執行時間

Traceview 是Android 平臺特有的數據采集和分析工具,它主要用于分析Android 中應用程序的hotspot(瓶頸)。Traceview 本身只是一個數據分析工具,而數據的采集則需要使用Android SDK 中的Debug 類或者利用DDMS 工具

1.1 Debug

開發者在一些關鍵代碼段開始前調用Android SDK 中Debug 類的startMethodTracing()函數,并在關鍵代碼段結束前調用stopMethodTracing()函數。這兩個函數運行過程中將采集運行時間內該應用所有線程(注意,只能是Java線程)的函數執行情況,并將采集數據保存到/mnt/sdcard/下的一個文件中。開發者然后需要利用SDK 中的Traceview工具來分析這些數據

1.2 DDMS

借助Android SDK 中的DDMS 工具。DDMS 可采集系統中某個正在運行的進程的函數調用信息。對開發者而言,此方法適用于沒有目標應用源代碼的情況。

觀察CPU的執行情況,測試的進程中每個線程運行的時間線,線程中各個方法的調用信息(CPU使用時間、調用次數等)

可以方便的查看線程的執行情況,某個方法執行時間、調用次數、在總體中的占比等,從而定位性能點

一般Traceview可以定位兩類性能問題

  • 方法調運一次需要耗費很長時間導致卡頓
  • 方法調運一次耗時不長,但被頻繁調運導致累計時長卡頓

DDMS 工具中Traceview 的使用如下圖所示。

點擊上圖中所示按鈕即可以采集目標進程的數據。當停止采集時,DDMS 會自動觸發Traceview 工具來瀏覽采集數據

2. Traceview的作用

查看跟蹤代碼的執行時間,分析哪些是耗時操作 ;可以用于跟蹤方法的調用,尤其是Android Framework層的方法調用關系

2.1 如何使用TraceView

使用TraceView主要有兩種方式:

最簡單的方式就是直接打開DDMS,選擇一個進程,然后按上面的“Start Method Profiling”按鈕,等紅色小點變成黑色以后就表示TraceView已經開始工作了。然后我就可以滑動一下列表(現在手機上的操作肯定會很卡,因為Android系統在檢測Dalvik虛擬機中每個Java方法的調用,這是我猜測的)。操作最好不要超過5s,因為最好是進行小范圍的性能測試。然后再按一下剛才按的按鈕,等一會就會出現下面的圖片,然后就可以開始分析了。

第2種方式就是使用android.os.Debug.startMethodTracing()和android.os.Debug.stopMethodTracing()方法,當運行了這段代碼的時候,就會有一個trace文件在/sdcard目錄中生成,也可以調用startMethodTracing(String traceName) 設置trace文件的文件名,最后你可以使用adb pull /sdcard/test.trace /tmp 命令將trace文件復制到你的電腦中,然后用DDMS工具打開就會出現下面那副圖片了

2.2 Debug

2.2.1 選擇追蹤范圍加入記錄代碼

首先,必須在程序當中加入代碼,以便生成trace文件,有了這個trace文件才可以將其轉化為圖形。

要添加的代碼如下:

Debug.startMethodTracing("wirelessqa");//開始 Debug.stopMethodTracing();//結束

其中參數wirelessqa是要創建的trace文件的名稱,wirelessqa.trace。默認路徑是/sdcard/wirelessqa.trace,也可以自己制定/data/log/wirelessqa,表示文件在/data/log/wirelessqa.trace。

2.2.2 實例代碼參考

publicclass MainActivity extends Activity {@Overrideprotectedvoid onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);setTitle(this.getClass().getName());View toLoginView = findViewById(R.id.to_login);// 開始記錄 sdcard/wirelessqa.trace文件Debug.startMethodTracing("wirelessqa");toLoginView.setOnClickListener(new View.OnClickListener() {publicvoid onClick(View view) {Intent intent = new Intent(getApplicationContext(), LoginActivity.class);startActivity(intent);}});}@Overrideprotectedvoid onStop() {super.onStop();Debug.stopMethodTracing();// 結束記錄wirelessqa.trace} }

說明:

開發文檔中說可以在activity的onCreate()中添加Debug.startMethodTracing(), 而在onDestroy()中添加Debug.stopMethodTracing(),但是在實際的測試時發現這種方式其實并不好用,因為通常情況下我們的activity的onDestroy()是由系統決定何時調用的,因此可能等了很長時間都不會得到這個trace文件。

因此決定在onStop()中來調用Debug.stopMethodTracing()。這樣當我們切換到其它activity或者點擊home鍵的時候onStop()就會被調用,我們也就可以得到完整的trace file

2.3 別忘了加入訪問SD卡的權限

<uses-permissionandroid:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

2.4 利用tools下的工具trace view打開.trace文件

第一種方式相對來說是一種簡單,但是測試的范圍很寬泛,第二中方式相對來說精確一點,不過我個人喜歡使用第一種,因為簡單,而且它是檢測你的某一個操作。因為第二中更適合檢測某一個方法的性能,其實也沒有那種好,看使用的場景和個人的喜好

效果圖:

2.5 看懂TraceView中的指標

下面我們具體分析一下這張圖(與上圖數據上有點區別):

2.6 縱軸

TraceView界面下方表格中縱軸就是每個方法,包括了JDK的,Android SDK的,也有native方法的,當然最重要的就是app中你自己寫的方法,有些Android系統的方法執行時間很長,那么有很大的可能就是你app中調用這些方法過多導致的

每個方法前面都有一個數字,可能是全部方法按照Incl CPU Time 時間的排序序號(后面會講到)

點一個方法后可以看到有兩部分,一個是Parents,另一個是Children。
Parent表示調用這個方法的方法,可以叫做父方法,Children表示這個方法中調用的其他方法,可以叫做子方法

2.7 橫軸

Incl Cpu Time

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

define inclusive : 全包括的
上圖中可以看到(toplevel) 的Incl Cpu Time 占了100%的時間,這個不是說100%的時間都是它在執行,請看下面代碼:

public void top() { a(); b(); c(); d(); }

Incl Cpu Time表示方法top執行的總時間,假如說方法top的執行時間為10ms,方法a執行了1ms,方法b執行了2ms,方法c執行了3ms,方法d執行了4ms(這里是為了舉個例子,實際情況中方法a、b、c、d的執行總時間肯定比方法top的執行總時間要小一點)

而且調用方法top的方法的執行時間是100ms,那么:

//Incl Cpu Time top 10% a 10% b 20% c 30% d 40%

從上面圖中可以看到:
toplevel的 Incl Cpu Time 是1110.943,而io.bxbxbai.android.examples.activity.ExpandableLayoutMainActivity$SimpleAdapter.getItemView方法的Incl Cpu Time為12.859,說明后者的Incl Cpu Time % 約為1.2%,這個指標表示 這個方法以及這個方法的子方法(比如top方法中的a、b、c、d方法)一共執行的時間

Excl Cpu Time

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

理解了Incl Cpu Time以后就可以很好理解Excl Cpu Time了,還是上面top方法的例子:

方法top 的 Incl Cpu Time 減去 方法a、b、c、d的Incl Cpu Time 的時間就是方法top的Excl Cpu Time 了

Incl Real Time

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

Excl Real Time

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

Calls + Recur Calls / Total

這個指標非常重要!它表示這個方法執行的次數,這個指標中有兩個值,一個Call表示這個方法調用的次數,Recur Call表示遞歸調用次數,看下圖:

我選中了一個方法,可以看到這個方法的Calls + Recur Calls 值是14 + 0,表示這個方法調用了14次,但是沒有遞歸調用
從Children這一塊來看,很多方法調用都是13的倍數,說明父方法中有一個判斷,但是這不是重點,有些Child方法調用Calls為26,這說明了這些方法被調用了兩遍,是不是可能存在重復調用的情況?這些都是可能可以優化性能的地方。

Cpu Time / Call

cpu time,這個指標應該說是最重要的,從上圖可以看到,133這個方法的調用次數為20次,而它的Incl Cpu Time為12.859ms,那么133方法每一次執行的時間是0.643ms(133這個方法是SimpleAdapter的getItemView方法)

對于一個adapter的getView方法來說0.643ms是非常快的(因為這個adapter中只有一個TextView,我為了測試用的)

如果getView方法執行時間很長,那么必然導致列表滑動的時候產生卡頓現象,可以在getView方法的Children方法列表中找到耗時最長的方法,分析出現問題的原因:

  • 是因為有過多的計算?
  • 還是因為有讀取SD卡的操作?
  • 還是因為adapter中View太復雜了?
  • 還是因為需要有很多判斷,設置View的顯示還是隱藏
  • 還是因為其他原因…

Real Time / Call

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

Real Time 和 Cpu Time 我現在還不太明白它們的區別,我的理解應該是:

  • Cpu Time 應該是某個方法占用CPU的時間
  • Real Time 應該是這個方法的實際運行時間

為什么它們會有區別呢?可能是因為CPU的上下文切換、阻塞、GC等原因方法的實際執行時間要比Cpu Time 要稍微長一點

3. 總結

TraceView是一個非常強大的性能分析工具,因為Android 官網對這個工具的使用介紹文檔很少,而且一些中文博客中寫的也都是抄來抄去,沒有講到底怎么使用

最近我在做這方面的性能分析,就慢慢琢磨了這么工具的使用,發現非常強大,寫下來總結一下

Android的性能分析工具還有很多,比如:

  • Eclipse Memory Analyzer Tool 來分析Android app的內存使用
  • Dump UI Hierarchy for UI Atomator,分析UI層級
  • Systrace:跟TraceView相似,只不過它是對整個系統進行分析
  • Lint工具:使用Lint進行資源及冗余UI布局等優化,Lint 有自動修復、提示建議和直接跳轉到問題處的功能
  • DDMS:Heap,Allocation Tracker

4. 其他

下圖這一條工具欄中有很多性能分析工具

5. Traceview 的使用

下面,我們通過一個示例程序介紹Traceview 的使用。

實例程序如下圖所示:界面有4 個按鈕,對應四個方法。

點擊不同的方法會進行不同的耗時操作。

public class MainActivity extends ActionBarActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}public void method1(View view) {int result = jisuan();System.out.println(result);}private int jisuan() {for (int i = 0; i < 10000; i++) {System.out.println(i);}return 1;}public void method2(View view) {SystemClock.sleep(2000);}public void method3(View view) {int sum = 0;for (int i = 0; i < 1000; i++) {sum += i;}System.out.println("sum=" + sum);}public void method4(View view) {Toast.makeText(this, "" + new Date(), 0).show();}}

我們分別點擊按鈕一次,要求找出最耗時的方法。點擊前通過DDMS 啟動Start Method Profiling 按鈕

然后依次點擊4 個按鈕,都執行后再次點擊上圖中紅框中按鈕,停止收集數據。

接下來我們開始對數據進行分析。

當我們停止收集數據的時候會出現如下分析圖表。該圖表分為2 大部分,上面分不同的行,每一行代表一個線程的執行耗時情況。main 線程對應行的的內容非常豐富,而其他線程在這段時間內干得工作則要少得多。圖表的下半部分是具體的每個方法執行的時間情況。顯示方法執行情況的前提是先選中某個線程。

我們主要是分析main 線程。上面方法指標參數所代表的意思如下:

列名描述
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 類似,只不過統計單位換成了真實時間

我們為了找到最耗時的操作,那么可以通過點擊Incl Cpu Time,讓其按照時間的倒序排列。我點擊后效果如下圖:

通過分析發現:method1 最耗時,耗時2338 毫秒。

那么有了上面的信息我們可以進入我們的method1 方法查看分析我們的代碼了

5.1 生成.trace文件

android.os.Debug類,其中重要的兩個方法

Debug.startMethodTracing(); Debug.stopMethodTracing();

這兩個方法用來創建.trace文件,將從Debug.startMethodTracing()開始,到Debug.stopMethodTracing()結束,期間所有的調用過程保存在.trace文件中,包括調用的函數名稱和執行的時間等信息。

6. dmtracedump

dmtracedump -g result.png target.trace //結果png文件 目標trace文件

參考:

  • https://bxbxbai.github.io/2014/10/25/use-trace-view/
  • http://blog.csdn.net/wirelessqa/article/details/8764622

總結

以上是生活随笔為你收集整理的性能分析工具 Android TraceView的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。