1. 程式人生 > 實用技巧 >Android效能優化案例研究(上)

Android效能優化案例研究(上)

>>> hot3.png

英文原文:Android Performance Case Study 編譯:ImportNew- 孫立

譯 者前言:

這是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(視窗)都有一個這樣 的表。為了使用這個資料,你可以簡單的將這個表拷到你最喜歡的電子製表軟體中,從而生成一個數據堆疊的列圖。以下這個圖就是我的測量結果。

每一列給出了每一幀花在渲染上的時間估計:

  1. “Draw”是指Java層用在建立“display lists”(顯示列表)上的時間。它表明執行例如View.onDraw(Canvas)需要多少時間。

  2. “Process”是指Android 2D渲染引擎用在執行“display lists”上的時間。你的UI層級(hierarchy)中的View數量越多,需要執行的繪畫命令就越多。

  3. “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,“設定”應用是什麼樣子。

如果你記得每種顏色所表示的含義,你就能很容易的知道結果是什麼:

  1. 沒有顏色就表示沒有重繪。每個畫素只畫了一次。在這個例子裡,你可以看到背景是完全無色的。

  2. 藍色:表示重繪了一次。每個畫素只畫了兩次。大塊的藍色是可以接受的。(如果整個window是藍色的,你就可以使用一個圖層(layer)。)

  3. 綠色:表示重繪了兩次。每個畫素畫了三次。中等尺寸的綠色方塊是可以接受的,但你最好嘗試做出優化。

  4. 紅色:表示重繪了三次。這個畫素被畫了四次。很小尺寸的紅色方塊是可以接受的。

  5. 黑色:表示重繪了四次及以上。這個畫素被畫了五次及以上。這個是錯的,需要解決。

基於這些資訊,你可以看到“設定”應用表現地很好,不需要額外的改進。只有在切換時有一點點紅塊,但不需要我們再做什麼工作了。

透明畫素:

再 仔細看看之前的截圖。每一個圖示都畫成了藍色。你可以看出點陣圖(bitmap)中透明畫素是解決了重繪的問題。透明畫素必須由GPU處理,開銷是昂貴的。 Android為了避免在圖層(layer)和9-patches上繪畫透明畫素,做了優化,所以你只要考慮點陣圖就行了。

重繪和GPU:

有 兩種移動GPU架構。第一個使用延遲渲染,比如ImaginationTech的SGX系列。這種架構允許GPU在某些特定的場景下檢查和處理重繪。(如 果你混合透明和不透明的畫素,它有可能不起作用。) 第二鍾架構使用及時渲染,它被NVIDIA的TegraGPU採用。這種架構不能為你優化重繪,這就是為什麼我喜歡在Nexus7上測試(Nexus7使 用Tegra3)。這兩種架構各有優劣。但這已經超出了本文的主題。僅僅只要知道兩者都可以工作的很好就行了。現在就讓我們看一下Falcon Pro…

截圖上有大量的紅色!最感興趣的卻是列表的背景是綠色的。這就顯示在應用程式開始描繪它的內容前已經發生了兩次重繪。我們這裡所看到問題很有可能是和使用了許多全屏圖片背景相關。但要解決這個問題通常是很繁瑣的。

轉載於:https://my.oschina.net/jerikc/blog/129711