android 動畫卡頓分析工具
android 動畫卡頓分析工具
Android應用效能優化之分析工具
上一次記錄瞭解決過度繪製的過程,這一次,想先弄清個概念性的東西,就是如何判斷順不順暢?
這東西其實最初我自己也覺得有點廢話,用起來會卡就明顯是不順暢咯。
但這東西就跟我很想吐槽很多應用一樣,明明那麼卡還放出來一樣的道理。
理論永遠是理論,實踐才是第一生產力。
因為我自己的應用也能感覺到卡頓,現在回頭分析,能明白,卡頓永遠不是“用心的程式設計師”原本的初衷,但很多東西,真心是難言之隱。
知錯就改才是好人...所以要改,就要知道究竟錯在哪。
1、縱觀全域性
對於順暢度的分析,首先要知道一個整體情況,是區域性,還是全域性,這樣在優化上才能有方向。
如果是區域性問題,那就需要仔細分析出具體的相關操作,如果是大體上的問題,那在思考的時候,就需要從整體的實現機制來考慮,有可能是實現方式上出現了問題。
在android4.1中,谷歌提供了一個工具來,叫做“ GPU呈現模式分析(Profile GPU rendering)”,在開啟這個功能後,系統就會記錄保留每個介面最後128幀影象繪製的相關時間資訊。
如果是在開啟應用後才開啟此功能,記得先把應用結束後重新啟動。
開啟後操作你需要分析的部分(比如滑動列表之類的),然後執行adb命令
$ adb shell dumpsys gfxinfo com.xxxx.xxx
在執行的結果中,有一塊叫做“Profile data in ms”底下有一堆資料.
Draw:表示在Java中建立顯示列表部分中,OnDraw()方法佔用的時間。
Process:表示渲染引擎執行顯示列表所花的時間,view越多,時間就越長
Execute:表示把一幀資料傳送到螢幕上排版顯示實際花費的時間。其實是實際顯示幀資料的後臺快取區與前臺緩衝區交換後並將前臺緩衝區的內容顯示到螢幕上的時間。所以這個時間,一般都很短。
PS:View類包含Surface(變數名mSurface),每個Surface通常對應兩個buffer,一個front buffer, 一個back buffer。(4.1之後是3個,一個前,兩個後)其中,back buffer就是canvas繪圖時對應的bitmap (研究Android_view_Surface.cpp::lockCanvas)。因此,繪畫總是在back buffer上,需要更新時,則將back buffer和front buffer互換。
Draw + Process + Execute = 完整顯示一幀 ,這個時間要小於16ms才能儲存每秒60幀。
將資料複製到excel中(win記得逐列複製,mac下就直接複製過去吧),然後將資料生成“堆積柱形圖”
從圖上看,能看出幾個現象。第一,確實4.1的黃油專案還真的有點作用,每幀的時間控制在16ms左右。第二,有幾幀超過16ms,確實會有丟幀的現象。
看來,頁面的卡頓應該是個別操作的問題。
但這種資料是否還能看出其他問題呢?
按照3個數據分別標示的內容,理論來講,如果UI執行緒佔用的時間過長,Draw的時間資料會應該會很長,所以做了個實驗,在UI執行緒中睡了1S。得到了下面這個圖。
從圖上看有幾幀Draw部分異常的高就能看出,Draw部分能看出UI執行緒的大體使用情況。
當然,其實這個資料主要能看出的是整體情況,單獨的某個部分跟測試的環境也有很大關係,比如一下2組資料,都是instagram的,同樣的資料,上面是Desire Z 4.1系統,下面是蓋3 4.1系統,在Execute部分,兩者有明顯的差距。
2、具體分析
“GPU呈現模式分析”的資料只能說明個現象,比如上面提到的資料,能說明在實際執行中會有短暫的長時間繪製問題。但造成問題的具體原因並沒有說明。
而且“GPU呈現模式分析”顯示的是最後128幀的資料,但丟幀也有可能是兩幀之間存在長時間的操作而造成的。
所以我們需要分析幀與幀之間的情況,才能對所分析應用的整體效能情況有個更升入的瞭解。
在android中提供了兩個工具來達到這個目的:1、Systrace (這工具坑的我....等下再吐槽) 2、traceview
Systrace是對整個系統進行分析,資料比較準確,當然也包括我們所要分析的應用。
當這個工具的使用是有條件限制的:
(1)是4.1之後才提供的工具。
(2)手機的核心一定要支援trace(可以檢視是否存在/sys/kernel/debug/tracing 這個目錄),所以很多第三方ROM或者三星之類的rom都在核心中remove了這個模組。模擬器裡面好像也都沒有。[這個坑的我刷了無數多的rom才找到適合的...之前的one x我記得好像也有,這個也間接說明一點,作為開發者,還是乖乖的買親兒子好]
Systrace的執行方式有兩種,一種是執行sdk包下的py檔案,這種要求的環境配置比較多。另一種就是在adt下的工具,點選直接執行。所以下面的使用介紹主要是這種。
在流暢程度的這種特殊分析情景下,我們一般只關注圖形效能。所以我們要選擇Graphics和View.還有其他很多選項,如果是在做音訊處理或者視訊播放的分析測試話,可以選擇其他選項。
確認執行之後,滾輪我們要測試的列表,工具會記錄5秒鐘的資料,之後我們回得到一個html頁面。開啟後,我們能看到頁面中顯示了系統中一切執行情況的概述。
瀏覽的操作時通過WASD來完成,W/S 放大/縮小 A/D 左移/右移
頁面中有個surfaceFlinger,知道android繪製原理的人應該能明白,這個就是負責繪製Android應用程式UI的服務,所以surfaceFlinger能反應出整體繪製情況,一般正常情況都是連續的,如果出現空檔,一種是沒有操作或者滑動到頭,沒東西需要繪製,這種屬於正常,另一種就是有問題存在,有其他操作時間過長。
對應所要分析的程式那行,放大後就能看到具體的情況,點選後能看到每個部分所使用的時間。
比如
deliverInputEvent是系統提供的觸控事件。
performTraversals是開始佈局並且繪畫顯示畫面的過程。
draw是繪畫的過程。
...
對於一個listview,如果deliverInputEvent過長,很有可能是在adapter中的getView方法中處理時間過長導致。
所以通過Systrace的資料,可以大體上的發現是否存在效能問題。
但如果要知道具體情況,就需要用到另外一個工具。
traceview
這個工具其實比較簡單,是一個分析器,記錄了應用程式中每個函式的的執行時間。在DDMS中,選中要分析的進場,點選“Start method profiling”(就是右上角有個紅點的圖示)。然後開始操作要分析的應用,然後再次點選按鈕來停止跟蹤。
然後下面顯示的資料應該挺通俗易懂的。
具體的可以參見:http://hubingforever.blog.163.com/blog/static/17104057920112825035143/
這裡我想介紹下我使用的一個經驗。
ViewRootImpl.draw(),這個是繪製函式,點選後,繪製的部分就會被突出出來。從理論上講,只要操作時沒有太多停頓,draw()的圖示應該是較為連續的。並且要保持順暢,每一個draw區域應該在16ms及以下。
所以一旦看到區域有大於16ms的,就可以認真分析下,看看都做了些什麼操作。從而找到導致繪製時間過長的問題所在。
對於這些工具的使用,雖然很大程度上能夠幫助我們更快的定位到問題之處,但還是有許多侷限的地方。
如果對android整體系統原理有一定的理解,並且深刻知道自己的程式的運轉情況,這樣分析起來,才會爐火純青。
以上是我個人的一些看法,希望能幫助到大家,沒寫的太細,夠用就好,因為有些部分,自己也有很多疑問,找到了一堆資料,發現也沒有說明的特別詳細的地方。
以下是參考的一些地方,大家可以去看看,有些需要走出去(怎麼出去這東西每個程式設計師都會吧?):
http://www.youtube.com/watch?v=Q8m9sHdyXnE(google IO的,需翻)
http://udinic.wordpress.com/2013/03/04/android-app-to-the-challenge/(
需翻)
http://www.curious-creature.org/docs/android-performance-case-study-1.html(需翻)
http://blog.chengyunfeng.com/?p=458(這個是上面的中文翻譯)