1. 程式人生 > >android客戶端native效能關注&&問題排查

android客戶端native效能關注&&問題排查

客戶端native效能

目前我們效能方面主要關注的點幀率、CPU、記憶體、流量、圖片、響應時間。以下對各點總結了下其標準、檢驗工具、問題排查。

一.     幀率

1.  標準:公司不同有可能不一致(遮蔽)

頁面靜默的時候GPU不應該再繪製(GPU呈現模式分析中沒有圖形變化)

2.  檢驗工具:自己公司開發的

3. 問題排查:

首先開啟手機上“開發者選項裡GPU呈現模式分析”檢視什麼操作下幀率繪製大於16ms,圖形有三種顏色:藍色、橙色、紅色。藍色表示測量繪製的時間;藍色的線很高的時候有可能是因為你的一堆檢視突然變得無效了(即需要重新繪製)或者自定義檢視的onDraw函式過於複雜紅色表示執行時間;

紅色的線非常高的時候有可能自定義view比較複雜,巢狀多另一種可能性是因為重新提交了檢視而導致的。橙色表示處理時間如果柱狀圖很高那就意味著你給GPU太多的工作太多的負責檢視需要OpenGL命令去繪製和處理也就是說view太多了總結起來就是view太多或者佈局複雜太深或者重新繪製沒有複用(特別是有些可以複用的必然listview,gridview之類的)。其次就是開啟“開發者選項裡的GPU過度繪製”來檢視究竟哪些view過度繪製了,有針對性的優化。佈局優化了還有問題,那麼影響幀率的因素還有:在啟動activity或者fragment頁面或者滑動頁面的時候同時有多執行緒或者網路請求等待
(traceview檢視執行緒執行和耗時情況),或者有GCtrceview時,
一般出現GC的時候時間線上會有比較大塊的同顏色的區域點選後就可以定位到函式面板區域的GC函式一步一步向parent函式追蹤就可以定位到GC的起因了),或者有重新繪製view的情況在滑動過程中或者有動畫的情況下做TraceView跟蹤可以發現是否被觸發了重新佈局在跟蹤結束中搜索onLayout或者layout或者requestlayout可以方便找到對應的控制元件

6動畫或者滑動過程是否觸發Layout動畫和滑動過程中在控制元件呼叫gone或者動態新增刪除重新設定paramsTextView重新設定文字以及重新設定

Drawable的時候都會觸發LayoutListViewgetview過程中它自己阻斷了這個requestlayout自己對子控制元件做了layout的操作所以不會引起整個介面的重新佈局但是如果在其他時間設定了圖片文字等就可能導致requestlayout被觸發進而執行onMeasure過程和onLayout過程這樣的話就會大大影響了滑動過程中的效能容易造成卡頓在滑動過程中或者有動畫的情況下做TraceView跟蹤可以發現是否被觸發了重新佈局在跟蹤結束中搜索onLayout或者layout或者requestlayout可以方便找到對應的控制元件

9檢視佈局效能問題通過Incl Cpu Time百分比排序列表滑動過程中如果看到onMeasure或者onLayout大於25%以上的就應該可以判斷出當前這個介面的佈局效能不佳需要優化了在列表滑動過程中也需要檢查getview這樣的函式的效能特別是佈局複雜的初始化時間會比較久10檢視佈局複用問題在列表滑動的過程中或者廣告Banner控制元件一般的做法都是應該複用佈局提升效能的但有時候因為覺得麻煩有些可能是動態新增的就沒有複用這些view導致在滑動過程中還是會出現infalte佈局的情況影響效能跟蹤方法是在這個列表已經滑動過的情況下開始進行TraceView這個時候來回滑動不應該出現infalte如果出現了就是複用出現了問題如下跟蹤發現有動態inflate button導致每次都額外增加了時間影響效能還有一種判斷方法就是在進入介面的時候找出LayoutInflater.createViewFromTag函式找出它數量以及parents呼叫方檢查是否有問題11判斷佈局巢狀過多或者過於複雜Call+RecurCalls/TotalCpuTime/Call放到最前面通過View/ViewGroupdraw呼叫次數和遞迴呼叫次數來判斷佈局的層級過多或者佈局Layout太多也可以通過buildDisplayList函式的呼叫和遞迴呼叫次數來判斷佈局的層級過多或者是Layout太多

二.  CPU

           1. 標準:CPU<75%,高CPU佔用時間不能太長,具體按實際情況定;靜默CPU<1%。

           2.  檢驗工具:公司開發的,用android studio也可以看

           3. 問題排查:

CPU突增,有可能是網路請求、複雜邏輯處理,具體情況要看這個時候的方法呼叫。高CPU佔用時間長的,有可能方法自己處理佔用時間長了,也有可能呼叫其他方法佔用時間長,也有可能反覆呼叫次數多了。這些具體情況可以用traceview工具檢視(用debug包),在操作時,點選那個紅點開始/結束(一般都是短時間的),之後看具體情況。


出現的圖分上下兩部分,上面部分可以直接看執行緒的執行時間長短,執行情況,下面是具體分析CPU使用時間和呼叫次數。首先是按照Incl Cpu Time檢視佔用時間長的,和哪些函式佔用多能找到具體方法其次看Call+Recur Calls/Total(把Call+Recur Calls/TotalCpu Time/Call放到最前面按照Call+Recur Calls/Total排序檢視執行次數多的隱患函式展開其子函式分析是否存在問題並通過Incl Cpu TimeCPU佔用比以及Incl Cpu Time的佔用百分比來判斷嚴重性特別是呼叫次數多的且Cpu Time/Call次數也多的應該重點排查

三.  記憶體

           1. 標準:。記憶體不能一直往上升:native應該沒什麼變化(c記憶體的分配),dalvik在一個範圍內波動(不能向上波動),不能波動太頻繁(記憶體抖動:記憶體抖動是因為大量的物件被建立又在短時間內馬上被釋放影響幀率),具體按實際情況定

          2. 檢驗工具: 公司開發的,用android studio也可以看。

         3. 問題排查:

記憶體抖動時一般是頻繁GCAllocation Tracker來檢視在短時間內分配的記憶體物件找到這些元凶Android Studio中的Memory Monitor也能檢視程式的記憶體使用情況以及檢視GC的情況。灰色部分為free,藍色的為實際佔用的。


記憶體洩露:記憶體增長的情況是存在沒有被回收的情況,那麼大部分是回收時被某個地方引用了,其生命週期更長。或者是無效的引用!

A.在DDMS中, 可以看到堆的大小和實際使用的大小,單一操作進行反覆操作,在GC後,如果堆的大小一直增加,則有記憶體洩漏的隱患。

 

或者用adbshell dumpsys meminfo檢視dalvik heap會不會持續增長。

B.利用在MAT分析dump hprof檔案。

然後用MAT分析hprof檔案(如果是現存檔案了,不可讀取時,還需要轉換./hprof-conv 原檔案目標檔案)。

首先看overview中有沒有明顯的leak佔用率和problem。

再是用Histogram檢視,針對某個關鍵詞搜尋檢視後按照objects或者retained heap排序後,右鍵list objects 可以檢視被引用(incoming)或者引用。然後對這些引用可以右健Path to GC Roots-->exclue all phantom/weak/soft etc. reference 查出某個例項沒被釋放的原因。用這個方法可以快速找到某個物件的 GC Root,一個存在 GC Root的物件是不會被GC回收掉的。

 

或者dominator Tree中按照Retained Memory排序找出比較大的然後用Path to GC Roots看看其引用情況在這個Path一般會發現我們app自己包的類可以分析這個類是不是還是需要的如果不需要那說明可能存在記憶體洩露此時在對這個自己包的類檢視incoming references看看到底是哪些引用導致它沒有釋放

更多使用和檢視原因可以網上查詢MAT使用。

四.  流量

          1. 標準:沒有突增大的流量(一次請求頁面突增大於2M時應該排查什麼情況下產生,單個response資料返回最好不要超過50kb),沒有重複請求 ;頁面靜默時或者處於後臺(沒有任何操作)不應該有流量增加了(有的話就要排查下什麼再耗流量了)。這個size的限制主要考慮到非WiFi情況下耗流量和網路網速對資料傳輸的影響。

2.  檢驗工具:公司開發工具,抓包看資料請求,或者log檢視是否有什麼耗流量(比如預設上傳資料,大量圖片下載)

  五.圖片

      1. 標準:網路請求圖片<50kb;

      2. 檢驗工具:直接抓包看下載下來的圖片多大

  六. 響應時間

          1. 標準:activity響應時間<1s(原來的計算方法oncreate到onresume)-2s(從activiy的onCreate到layout的第五幀耗時)第二種方案:

  以Activity onCreate為起點,頁面檢測到檢視繪製5次後結束(通過監聽DecorView PreDraw事件。onCreate是業務執行時間真正開始,在PreDraw 5次後檢視框架基本已經載入完成。測試過程中發現,在第3次PreDraw之前,ActivityManagerDisplayed time已經計算出來,這也是為什麼通過ActivityManager Displayedtime不能反映載入耗時原因,而Activity onCreate 到onResume的時間跟柵欄這兩種方案,都只是ActivityManager Displayedtime過程的一部分

        2. 原始碼中埋點