安卓應用效能除錯和優化經驗分享

安卓綠色聯盟發表於2019-02-20

安卓綠色聯盟應用效能標準主要基於主觀體驗、資源消耗和應用質量三個方面進行制定。

1、主觀體驗

主觀體驗主要是對應用啟動時間和介面幀率制定標準,要求應用在視覺上足夠流暢。其中應用啟動時間又分為冷啟動時間和熱啟動時間。

安卓綠色聯盟效能標準要求,應用冷啟動時間需小於1000ms,熱啟動時間需小於500ms;普通應用幀率應大於55fps,遊戲視訊幀率應大於25fps。

2、資源消耗

資源消耗主要是要求應用不能佔用過高的記憶體和CPU。

安卓綠色聯盟效能標準要求應用前臺記憶體佔用應小於500M,後臺記憶體佔用應小於400M;在CPU佔用方面要求應用在後臺滅屏5分鐘後,CPU佔用不超過2%。

3、應用質量

應用質量主要是對應用過度繪製和記憶體洩露的情況作出要求,規定應用不能存在過度繪製和記憶體洩露。

安卓綠色聯盟效能標準要求應用介面任意畫素點不存在4x的繪製的情況, 3x繪製的區域不能超過介面面積的1/3,在Strict Mode中不允許有紅框閃爍。

效能除錯方法

在瞭解效能除錯方法之前,我們可以先通過下圖瞭解安卓應用效能與系統之間的關係。一個應用從應用繪製到最終顯示在LCD上經歷了一個漫長的路徑,在任何一個階段出現延時都會導致介面上的卡頓。

image

1、Strict Mode

Strict Mode意思為嚴格模式,是Android提供的一種執行時檢測機制,一般用來檢測在主執行緒發生的耗時動作,比如IO讀寫、資料庫操作、複雜演算法等。在手機設定開發者選項把Strict Mode開啟,就可以在介面上把它開啟了。

嚴格模式主要有2個策略,一個是執行緒策略,即ThreadPolicy,主要檢測主執行緒中的一些耗時操作;另一個是虛擬機器策略,即VmPolicy,主要檢測一些物件的洩漏。

兩大策略檢測的內容和開啟方法可以依據下圖中的說明進行使用。

image

嚴格模式有三種懲罰模式:應用崩潰、彈窗警告和列印日誌。在效能測試中,我們可以通過APPLogcat抓取Strict Mode的日誌,同時利用程式碼啟用Strict Mode,配合我們所需要的策略和懲罰,就可以及時定位應用的違規細節,並及時進行效能優化。

當我們碰到違規的行為時,該如何進行治理呢?建議將檔案操作放到工作執行緒去完成,如果在主執行緒上提及操作,建議使用Apply和Commit去完成。如果存在物件未關閉的情況,可以通過對應的StackTrace進行關閉。

2、OverDraw DeBugger

Overdraw是指螢幕上的某個畫素在同一幀的時間內被繪製了多次,這個工具使用色塊來代表不同數量的過度繪製,我們可以使用這個工具來定位由過度繪製引起的使用者介面卡頓問題。

在開發者選項中選擇開啟 Debug GPU Overdraw選項,即可在安卓裝置上將過度繪製問題視覺化。

image

左圖為正常模式下顯示的檢視,右圖為開啟GPU Overdraw後顯示的檢視

3、Profile GPU Rendering

ProfileGPU Rendering 工具以滾動直方圖的形式直觀地顯示渲染介面視窗幀所花費的相對時間(以每幀 16 毫秒的速度作為對比基準)。這個工具同樣也是在安卓裝置的開發者選項中開啟。每個管線的高度表示時間,管線中各個彩色區段代表不同含義。

下表介紹了使用執行Android 6.0及更高版本的裝置時分析器中不同豎條區段的含義。

image

4、Android Profiler

Android Profiler是一個Android Studio整合的應用效能分析器,可以實時檢視CPU、Memory和Network的動態情況。以下重點介紹CPU Profiler:

CPU Profiler 可幫助您實時檢查應用的 CPU 使用率和執行緒 Activity,並記錄函式跟蹤,方便大家優化和除錯應用程式碼。

當開啟 CPU Profiler 時,它將顯示應用的 CPU 使用率和執行緒 Activity。

image

CPU Profiler可以選擇不同的標籤,並對應用執行緒進行跟蹤。如:

(1)Flame Chart標籤會提供一個倒置的呼叫圖表,彙總相同的呼叫堆疊,收集呼叫順序完全一致的函式,並在火焰圖中用一個較長的橫條表示它們。

(2)Top Down標籤能夠提供每個函式呼叫上所花費的CPU時間。Self表示函式呼叫在執行自己的程式碼上所花的時間;Children表示函式呼叫子方法所花費的時間;Total表示Self和Children時間的總和。

5、Systrace

Systrace是我們分析效能最常用的工具之一,它可以分析整機系統效能及動態場景的效能問題。

Systrace 允許您在系統級別收集和檢查裝置上執行的所有程式的計時資訊。它將來自Android核心的資料(例如CPU排程程式,磁碟活動和應用程式執行緒)組合起來,以生成HTML報告。

image

上圖左部是Systrace的介面,我們可以通過右邊的程式碼抓取Systrace,觀察程式的執行時間。在輸入抓取命令時,時間引數一般選擇5到10秒,因為時間過短可能會抓不到想要的資料,時間過長則可能抓取失敗。

一般我們通過Chrome瀏覽器檢視生成的trace檔案,也可以通過DDMS圖形介面去抓取Systrace。

image

拿到一個Systrace時主要考察哪些因素?首先看一下CPU的頻率,找到對應的程式或者執行緒,檢視相關資訊;同時還要觀察GPU的頻率、Surface Flinger還有繪圖的Buffer狀態等。

當應用發生卡頓時,我們可以通過Systrace進行分析。在生成的trace檔案中,找到主執行緒UI,每一幀都會標記一個帶有F的圓形。當原型為綠色時,代表頁面流暢,而黃色和紅色則存在超時,我們可以點選去檢視具體存在什麼問題。

效能案例分析

案例1:介面滑動卡頓

image

從圖中可以看到,這是一個手動滑動事件,當deliverInput事件發生後,第一幀就發生了卡頓。從systrace看UI thread執行draw的時間相當耗時導致丟幀卡頓,而且大部分時間都在做decodeBitmap,共耗時99.045ms。這時,我們開啟applog發現,有StrictMode相關的錯誤提示,從中可以定位到耗時函式。

image

從上圖我們看出有一個網路訪問違規,大概可以推測應用在從網路上下載了一個資料流,資料流裡可能包含了一些圖形,通過decodeBitmap把它解析出來展示在UI介面中。正產情況下,我們應該把網路訪問放在工作執行緒裡面去處理,將資料下載完了之後再放到主執行緒中去展示,避免這種問題的發生。

案例2:Strict Mode錯誤提示

image

從上圖Strict Mode的日誌可以看出:StrictMode policy violation耗時2秒左右。通過最下行藍色的log,可以知道應用是在某一個目錄裡面尋找一個檔案,判斷檔案是否存在。

面對這種問題,我們應該把IO操作放到工作執行緒。正常情況下IO的發生非常快,但是在系統繁忙時,IO放在主執行緒會產生較大的問題,因為它要等別的程式讀寫完成之後,才會下發,產生超時。

案例3:GPU呼叫不當導致的卡頓問題

image

這是一個GPU的例子,上圖主要問題是GPU使用了太長時間處理應用傳過來的buffer,例子中Surfaceflinger 使用GPU 做了影象疊加,說明圖層比較多。使用GPU做疊加主要會產生功耗和喚醒耗時的問題。大家在做介面設計的時候,儘量不要使用GPU進行疊加。在上面的例子中,GPU疊加之後,導致了大概15ms左右的延時,因為GPU操作完成以後還需要交給Surfaceflinger把影象顯示到螢幕上。

案例4:CPU呼叫不當導致的介面滑動卡頓問題

image

可以通過上圖的紅色條塊瞭解messageloop RunTask資訊,紅色條塊上的藍色bar,表示執行緒在CPU上的狀態。藍色表示這個執行緒處於等待CPU排程的狀態,可見等待超過8ms的時間,是正常排程週期好幾倍。導致這種情況發生的原因有兩個:CPU負載過大或CPU排程出現了問題。在上圖中我們可以看出,CPU0和CPU1使用率100%,但是CPU2和CPU3是offline的狀態,說明系統出現問題,導致CPU2和CPU3未能喚醒,幫助完成系統任務。

效能優化建議

1、避免記憶體洩露

在應用開發過程中,首先要避免記憶體洩露的問題,記憶體洩露是一種比較嚴重的效能問題,在安卓綠色聯盟應用效能標準中也要求應用不允許發生記憶體洩露。

下圖是常見的記憶體洩露防範方法和記憶體洩露檢測工具。

image

2、避免不良設計或程式演算法導致CPU佔有率持續偏高

主要業務處理分散到不同執行緒,便於後續利用多核處理器的並行處理能力,避免一核累死,7核圍觀; 使用top命令觀察應用執行緒的CPU佔有率,找出高負載的程式進行分析,並針對優化。

3、避免OnXXX 回撥函式中進行耗時操作,避免主執行緒卡頓

Android系統中正常情況下所有onXXX類函式均執行在主執行緒中。

image

在上圖中,我們可以看到兩幀中間有一個因為接收廣播處理導致的158ms的卡頓。在這些函式中,我們應該避免網路通訊操作、檔案讀寫操作、資料庫資料改動的操作、圖形處理、文字分析等操作,將這些工作儘可能的移到工作執行緒中去,從而避免主執行緒卡頓。

4、合理使用系統資源

合理使用系統資源主要指的是軟資源。下圖是對廣播資源呼叫的一些建議。

image

關注安卓綠色聯盟公眾號,回覆關鍵詞“23”,獲取PPT。

相關文章