天天看點

正确使用 Android 性能分析工具——TraceView

最近公司app中有些清單在滑動的時候會有卡頓現象,我就開始着手解決這些問題,解決問題之前首先要分析清單滑動的性能瓶頸在什麼地方。因為之前不會正确使用traceview這個工具,主要是看不懂traceview界面下方資料名額的值代表什麼意思…以前我用stopwatch類來分析性能,現在覺得弱爆了…不過有些地方stopwatch工具類還是很簡單好用的~

網上可以找了很多部落格來介紹這個工具的使用方法,很多都是講解了一些一些就會的方法,講一個大概,包括stackoverflow上我也沒有找到很好的講解traceview各個資料名額代碼什麼意思的回答

因為我要解決清單滑動的卡頓問題,就必須要找到導緻卡頓現象的原因,我就在stackoverflow上找着别人零散的回答慢慢琢磨這個工具的使用方法。現在我學會了,至少能看懂每個名額什麼意思,最後發現這個工具實在太強大了!!!

現來看一下整個界面的圖,整個界面包括上下兩部分,上面是你測試的程序中每個線程的執行情況,每個線程占一行;下面是每個方法執行的各個名額的值

上面一部分是你測試程序的中每個線程運作的時間線,下圖中可以可以看到,主要隻有一個main線程在執行,因為我滑動了一下清單,main線程(ui線程)正在進行繪制view呢~

然後我點選了序号為133的一個方法io.bxbxbai.android.examples.activity.expandablelayoutmainactivity$simpleadapter.getitemview,就會出現兩部分資料:

parents

children

parents表示調用133這個方法的父方法,可以看到序号為130。children表示方法133調用的其他方法,可以看到有好幾個方法。

正确使用 Android 性能分析工具——TraceView

因為這次我主要是分析清單滑動卡頓問題,我就講講我是怎麼使用這個工具的,并且我是怎麼分析的。

使用traceview主要有兩種方式:

1.最簡單的方式就是直接打開ddms,選擇一個程序,然後按上面的“start method profiling”按鈕,等紅色小點變成黑色以後就表示traceview已經開始工作了。然後我就可以滑動一下清單(現在手機上的操作肯定會很卡,因為android系統在檢測dalvik虛拟機中每個java方法的調用,這是我猜測的)。操作最好不要超過5s,因為最好是進行小範圍的性能測試。然後再按一下剛才按的按鈕,等一會就會出現上面這幅圖,然後就可以開始分析了。

2.第2種方式就是使用android.os.debug.startmethodtracing();和android.os.debug.stopmethodtracing();方法,當運作了這段代碼的時候,就會有一個trace檔案在/sdcard目錄中生成,也可以調用startmethodtracing(string tracename) 設定trace檔案的檔案名,最後你可以使用adb pull /sdcard/test.trace /tmp 指令将trace檔案複制到你的電腦中,然後用ddms工具打開就會出現第一幅圖了

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

正确使用 Android 性能分析工具——TraceView

其實我今年7月份就已經開始使用traceview工具了,但是當時不懂其中每個名額的含義,就沒注意到它強大的地方。看不懂界面下方表格中的名額,這些資料其實一點意義都沒有。

網上包括android官網也沒有對traceview工具的使用有詳細的說明文檔,這點确實比較蛋疼。

縱軸

traceview界面下方表格中縱軸就是每個方法,包括了jdk的,android sdk的,也有native方法的,當然最重要的就是app中你自己寫的方法,有些android系統的方法執行時間很長,那麼有很大的可能就是你app中調用這些方法過多導緻的。

每個方法前面都有一個數字,可能是全部方法按照incl cpu time 時間的排序序号(後面會講到)

點一個方法後可以看到有兩部分,一個是parents,另一個是children。

parent表示調用這個方法的方法,可以叫做父方法

children表示這個方法中調用的其他方法,可以叫做子方法

橫軸

正确使用 Android 性能分析工具——TraceView

橫軸上是很多名額,這些名額表示什麼意思真的困擾了我很長一段時間。。。

能夠很衡量一個方法性能的名額應該隻有時間了吧? 一個方法肯定就是執行時間越短約好咯~~

incl cpu time

define inclusive : 全包括的

上圖中可以看到0(toplevel) 的incl cpu time 占了100%的時間,這個不是說100%的時間都是它在執行,請看下面代碼:

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

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

正确使用 Android 性能分析工具——TraceView

從上面圖中可以看到:

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

了解了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

這個感覺和incl cpu time 差不多,第7條會講到。

excl real time

同上

calls + recur calls / total

這個名額非常重要!

它表示這個方法執行的次數,這個名額中有兩個值,一個call表示這個方法調用的次數,recur call表示遞歸調用次數,看下圖:

正确使用 Android 性能分析工具——TraceView

我選中了一個方法,可以看到這個方法的calls + recur calls 值是14 + 0,表示這個方法調用了14次,但是沒有遞歸調用

從children這一塊來看,很多方法調用都是13的倍數,說明父方法中有一個判斷,但是這不是重點,有些child方法調用calls為26,這說明了這些方法被調用了兩遍,是不是可能存在重複調用的情況?這些都是可能可以優化性能的地方。

cpu time / call

重點來了!!!!!!!!!!

正确使用 Android 性能分析工具——TraceView

這個名額應該說是最重要的,從上圖可以看到,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

real time 和 cpu time 我現在還不太明白它們的差別,我的了解應該是:

cpu time 應該是某個方法占用cpu的時間

real time 應該是這個方法的實際運作時間

為什麼它們會有差別呢?可能是因為cpu的上下文切換、阻塞、gc等原因方法的實際執行時間要比cpu time 要稍微長一點。

traceview是一個非常強大的性能分析工具,因為android 官網對這個工具的使用介紹文檔很少,而且一些中文部落格中寫的也都是抄來抄去,沒有講到底怎麼使用。

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

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

eclipse memory analyzer tool 來分析android app的記憶體使用

dump ui hierarchy for ui atomator,分析ui層級

systrace

其他

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

正确使用 Android 性能分析工具——TraceView

繼續閱讀