Android性能優化案例研究(上)
轉自:
https://www.importnew.com/3784.html
譯 者前言:
這是Google的Android開發工程師Romain Guy刊登在個人Blog上的一篇文章。Romain Guy 作為Android圖形渲染和係統優化的專家,是Android 4.1中的“黃油項目”開發者之一。這篇譯文將分為上下兩個部分,上部分將通過一個實際的例子來展示如何利用現有的工具來定位Android應用程序的性能瓶頸,下部分將提供一些有效的方法來解決性能問題。希望能給讀者和開發者帶來啟發和借 鑒。
Falcon Pro
最近我在我的Nexus4上安裝了Falcon Pro(下 圖),一個新款的推特(Twitter)客戶端。我覺得這款應用真的很讚,但我也注意到一些使用時的瑕疵:似乎在劃屏滾動主界麵的時間軸時,幀率並不能很 穩定。於是我利用我每天工作中所使用的工具和方法對此稍加研究,很快發現了Falcon Pro不能達到其應有性能的一些原因。

我這篇文章的主旨在於告訴你如何在一個應用中追蹤和定位性能問題,甚至在沒有它的源代碼的情況下。你所要做的隻是要獲得最新的Android4.2SDK(最新的ADT工具可以幫你輕而易舉的完成此事)。我強烈推薦你“能夠”去下載這款有待研究的應用。不幸的是,Falcon Pro是一款付費應用,我因此隻能提供一些文件的鏈接以便你能對照我的分析。
說說關於性能優化
Android4.1通過“黃油項目”將焦點放在性能優化上,並且它也引入了一些性能分析的工具,比如systrace。Android4.2並沒有提供像systrace那樣顯著的工具,但也為你的工具集增加了一些很有用的功能。你將會在接下來的篇幅中發現到它們。(黃油計劃 Project Butter,是Google在 Android 4.1 Jellybean版本開始啟動的Android性能提升計劃,其寓意為“像黃油一樣順滑”,該項目主要針對Android長期以來的飽受詬病的運行流暢度問題,通過底層的優化,確保係統設備能達到60fps的幀刷新率,從而大大提高用戶體驗的流暢性——譯者注)
性能分析通常是一項複雜的任務,它需要大量的經驗,需要對工具,硬件,API等方麵的深入理解。這些經驗讓我在這隻要幾分鍾就可以做出分析(你可以在我12月1日的推特(Twitter)上看到它的實況轉播。)而你可能得試上幾次後才能對此得心應手。
證實我的疑問
記 憶中關於性能優化最重要的一件事就是通過量化來驗證你的工作。即使對我而言,Falcon Pro在的Nexus4上有著很明顯的丟幀現象,我仍然得用實際的數據來證明。因此我將這款應用安裝到Nexus7上,因為Nexus7比Nexus4性 能更強大,同時Nexus7在性能分析上也有著比Neux4更有意思的優勢,關於這一點,我將在稍後加以討論。
這 款應用安裝到Nexus7上也沒有出現多大差別,我仍然能看到丟幀的現象甚至還略差。為了量化這個問題,我決定使用“Profile GPU rendering”(GPU渲染分析),一款Android4.1所引入的工具。你可以在“設置”應用的“開發者選項”中找到這個工具。
如果開發者選項在你的Android4.2設備上不可見,你可以在“關於手機”或者“關於桌麵選擇”的界麵底部,點擊“版本號”七次。

我這篇文章的主旨在於告訴你如何在一個應用中追蹤和定位性能問題,甚至在沒有它的源代碼的情況下。你所要做的隻是要獲得最新的Android4.2SDK(最新的ADT工具可以幫你輕而易舉的完成此事)。我強烈推薦你“能夠”去下載這款有待研究的應用。不幸的是,Falcon Pro是一款付費應用,我因此隻能提供一些文件的鏈接以便你能對照我的分析。

當這個選項打開,係統將會記錄畫每個窗口繪畫最後128幀所需要的時間。在使用這個工具前,你得先殺掉這個應用(Android未來的版本將會去掉這個要求)。
方法:
除非特別需要,在為這個分析做每一次測量時,需緩慢的滾動主界麵的時間軸,讓其滾動一段像素,使其能展現額外的條目。
在重新啟動這個應用並滾動時間軸主界麵時,我在終端上運行了下麵這個命令:
$ adb shell dumpsys gfxinfo com.jv.falcon.pro
在 產生的日誌中,你會發現一段標記為“Profile”的毫秒量級的數據。這段數據包含了一個有三列數據的表,應用的每個window(窗口)都有一個這樣 的表。為了使用這個數據,你可以簡單的將這個表拷到你最喜歡的電子製表軟件中,從而生成一個數據堆疊的列圖。以下這個圖就是我的測量結果。

每一列給出了每一幀花在渲染上的時間估計:
-
“Draw”是指Java層用在創建“display lists”(顯示列表)上的時間。它表明運行例如View.onDraw(Canvas)需要多少時間。
-
“Process”是指Android 2D渲染引擎用在執行“display lists”上的時間。你的UI層級(hierarchy)中的View數量越多,需要執行的繪畫命令就越多。
-
“Execute”是指將一幀圖像交給合成器(compositor)的時間。這部分占用的時間通常比較少
提醒:
要以60fps的幀率進行平滑的渲染,每一幀所占用的時間需要少於16ms。
關於“Execute”:
如 果Excute花費很多時間,這就意味著你跑在了係統繪圖流水線的前麵。Android在運行狀態時最多可以用3塊緩存,如果此時你的應用還需要一塊緩 存,那應用就會被阻塞直到三塊中的一塊緩存被釋放。這種情況的發生一般有兩個原因。第一個原因是你的應用在Dalvik(java虛擬機)端畫的太快,而 在它的Display list在GPU端執行太慢。第二個原因是你的應用花費太多時間在前幾幀的渲染上,一旦流水線滿了,它就跟不上,直到動畫的完成。這些是我們想在下一個版 本的Android改進的地方。
以上這個圖明顯的證實了我的疑慮:這個應用在大部分時間運行良好,但某些時候會發生丟幀。
進一步研究
我們收集的數據顯示這個應用有時繪圖時間過長,但蓋棺定論還為時過早。幀率也會被未調度的幀或者錯過調度的幀的影響。例如,如果應用總是在16ms內完成一次繪圖,但有時在幀與幀之間需要完成很長的任務,它就會因此錯過一幀。
Systrace是一個很簡單的工具去檢查Falcon Pro是否存在這個問題。這個工具是係統級的,額外開銷很低。它的時間統計是合理準確的,能給你一個整個係統運行的概況,包括你的應用。
開啟Systrace,可以到開發者選項中選擇“啟動跟蹤”,彈出一個對話框,會讓你選擇你想測量哪些方麵的性能。我們隻關注“Graphics”和“View”。
注意:
不要忘記關掉之前的GPU渲染分析選項。

使用systrace時,可以打開終端,在Android SDK的tools/systrace目錄下,運行systrace.py:
$./systrace.py
這個工具默認會記錄5秒鍾內發生的事件。我簡單的向上和向下滾動時間軸,得到了一個用HTML文檔展現的結果圖。
技巧:
瀏覽systrace的文檔圖,可以使用鍵盤上的WASD鍵去移動和縮放。W鍵是將鼠標所處位置進行放大。
systrace 的文檔圖顯示了很多有意思的信息。例如,它可以顯示一個進程是否被調度,是在哪個CPU上調度。如果你放大最後一行(叫做 10440:m.jv.falcon.pro),你可以看到這個應用正在做什麼。如果你點擊一個“performTraversals”塊,你可以看到這 個應用花在輸出一幀圖像上麵多長時間。
大多數的performTraversals顯示在16ms臨界值以下,但有一些需要更多的時間,因此也證實了之前的猜測。(在935毫秒處放大可以看到這個塊。)
更 有意思的是,你可以看到這個應用有時錯過一幀是因為它沒有管理調度一個draw的操作。在270ms處放大,找到占用25ms的 “deliverInputEvent”塊。這個塊表明這個應用用了25ms來處理一個觸摸事件。考慮到這個應用是使用ListView,很有可能是這個 適配器(adapter)出了問題,等會我們再來探討這個。Systrace很有用的地方不僅在於證實這個應用花在繪圖的時間上太長,也在於幫我們找到另 一個潛在的性能瓶頸。它很有用但也有局限。它隻能提供高層級的數據,我們必須轉向其他工具來理解此時究竟在運行什麼。
可視化重繪
繪 圖性能問題有很多根本的原因,但共同的一點是重繪(overdraw)。重繪發生在每次應用讓係統在某個畫好的地方上麵再畫別的。想一個最簡單的應用:一 個白色背景的窗口(window),上麵是一個按鈕。當係統要畫這個按鈕時,它要畫在已經畫好的白色背景的上麵。這就是重繪。重繪是必然的,但太多的重繪 就是個問題。設備的數據傳輸帶寬是有限的,當重繪使得你的應用需要更多的帶寬時,性能就會下降。不同的設備能夠承擔的重繪的代價是不同的。
最佳的準則是重繪的最大次數不能超過兩次。這就意味著你可以在屏幕畫第一次,然後在這個屏幕上再畫第二次,最後在其中某些像素上再畫第三次。
重繪的存在通常表明有這些問題:太多的View,複雜的層級,更長的inflation時間等等。
Android提供了三個工具來幫助辨別和解決重繪問題:Hierachy Viewer,Tracer for OpenGL和Show GPU overdraw。前兩個可以在ADT工具或者獨立的monitor工具中找到,最後一個是在開發者選項的一部分。
Show GPU Overdraw會在屏幕上畫不同的顏色來辨別重繪發生在哪兒,重繪了幾次。現在就開啟它並且別忘了先殺掉你的應用(將來版本的Android會去掉這個要求)。

在我們查看Falcon Pro之前,讓我們先看看當打開Show GPU overdraw,“設置”應用是什麼樣子。

如果你記得每種顏色所表示的含義,你就能很容易的知道結果是什麼:
-
沒有顏色就表示沒有重繪。每個像素隻畫了一次。在這個例子裏,你可以看到背景是完全無色的。
-
藍色:表示重繪了一次。每個像素隻畫了兩次。大塊的藍色是可以接受的。(如果整個window是藍色的,你就可以使用一個圖層(layer)。)
-
綠色:表示重繪了兩次。每個像素畫了三次。中等尺寸的綠色方塊是可以接受的,但你最好嚐試做出優化。
-
紅色:表示重繪了三次。這個像素被畫了四次。很小尺寸的紅色方塊是可以接受的。
-
黑色:表示重繪了四次及以上。這個像素被畫了五次及以上。這個是錯的,需要解決。
基於這些信息,你可以看到“設置”應用表現地很好,不需要額外的改進。隻有在切換時有一點點紅塊,但不需要我們再做什麼工作了。
透明像素:
再 仔細看看之前的截圖。每一個圖標都畫成了藍色。你可以看出位圖(bitmap)中透明像素是解決了重繪的問題。透明像素必須由GPU處理,開銷是昂貴的。 Android為了避免在圖層(layer)和9-patches上繪畫透明像素,做了優化,所以你隻要考慮位圖就行了。
重繪和GPU:
有 兩種移動GPU架構。第一個使用延遲渲染,比如ImaginationTech的SGX係列。這種架構允許GPU在某些特定的場景下檢查和處理重繪。(如 果你混合透明和不透明的像素,它有可能不起作用。) 第二鍾架構使用及時渲染,它被NVIDIA的TegraGPU采用。這種架構不能為你優化重繪,這就是為什麼我喜歡在Nexus7上測試(Nexus7使 用Tegra3)。這兩種架構各有優劣。但這已經超出了本文的主題。僅僅隻要知道兩者都可以工作的很好就行了。現在就讓我們看一下Falcon Pro…

截圖上有大量的紅色!最感興趣的卻是列表的背景是綠色的。這就顯示在應用程序開始描繪它的內容前已經發生了兩次重繪。我們這裏所看到問題很有可能是和使用了許多全屏圖片背景相關。但要解決這個問題通常是很繁瑣的。
譯者注:下篇作者將會帶來如何解決性能問題的方法和思路,敬請期待!
英文原文:Android Performance Case Study 編譯:ImportNew - 孫立
譯文地址: https://www.importnew.com/3784.html
最後更新:2017-04-03 07:57:08