客戶端native性能
目前我們性能方面主要關注的點幀率、CPU、內存、流量、圖片、響應時間。以下對各點總結了下其標準、檢驗工具、問題排查。
一. 幀率
1. 標準:公司不同有可能不一致(屏蔽)
頁面靜默的時候GPU不應該再繪製(GPU呈現模式分析中沒有圖形變化)
2. 檢驗工具:自己公司開發的
3. 問題排查:
首先打開手機上“開發者選項裏GPU呈現模式分析”查看什麼操作下幀率繪製大於16ms,圖形有三種顏色:藍色、橙色、紅色。藍色表示測量繪製的時間;藍色的線很高的時候,有可能是因爲你的一堆視圖突然變得無效了(即需要重新繪製),或者自定義視圖的onDraw函數過於複雜。紅色表示執行時間;紅色的線非常高的時候,有可能自定義view比較複雜,嵌套多;另一種可能性是因爲重新提交了視圖而導致的。橙色表示處理時間;如果柱狀圖很高,那就意味着你給GPU太多的工作,太多的負責視圖需要OpenGL命令去繪製和處理;也就是說view太多了。總結起來就是view太多,或者佈局複雜太深,或者重新繪製沒有複用(特別是有些可以複用的必然listview,gridview之類的)。其次就是打開“開發者選項裏的GPU過度繪製”來查看究竟哪些view過度繪製了,有針對性的優化。佈局優化了還有問題,那麼影響幀率的因素還有:在啓動activity或者fragment頁面或者滑動頁面的時候同時有多線程或者網絡請求等待(traceview查看線程執行和耗時情況),或者有GC(trceview時,一般出現GC的時候時間線上會有比較大塊的同顏色的區域點擊後就可以定位到函數面板區域的GC函數一步一步向parent函數追蹤就可以定位到GC的起因了),或者有重新繪製view的情況(在滑動過程中或者有動畫的情況下做TraceView跟蹤可以發現是否被觸發了重新佈局。在跟蹤結束中搜索onLayout或者layout或者requestlayout可以方便找到對應的控件。)
6、動畫或者滑動過程是否觸發Layout
動畫和滑動過程中在控件調用gone或者動態添加刪除重新設置paramsTextView重新設置文字以及重新設置Drawable的時候都會觸發Layout。在ListView的getview過程中它自己阻斷了這個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/Total和CpuTime/Call放到最前面通過View/ViewGroup的draw調用次數和遞歸調用次數來判斷佈局的層級過多或者佈局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/Total和Cpu Time/Call放到最前面按照Call+Recur Calls/Total排序查看執行次數多的隱患函數展開其子函數分析是否存在問題並通過Incl Cpu Time的CPU佔用比以及Incl Cpu Time的佔用百分比來判斷嚴重性特別是調用次數多的且Cpu Time/Call次數也多的應該重點排查。)
三. 內存
1. 標準:。內存不能一直往上升:native應該沒什麼變化(c內存的分配),dalvik在一個範圍內波動(不能向上波動),不能波動太頻繁(內存抖動:內存抖動是因爲大量的對象被創建又在短時間內馬上被釋放。影響幀率),具體按實際情況定
2. 檢驗工具: 公司開發的,用android studio也可以看。
3. 問題排查:
內存抖動時一般是頻繁GC,用Allocation 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. 源代碼中埋點