android每秒
『壹』 androidUI卡頓原理分析及Vsync信號機制
一、UI卡頓定義
1、用戶角度:app操作界面刷新緩慢,響應不及時;界面滑動不夠流暢;
2、系統角度:屏幕刷新幀率不穩定,掉幀嚴重,無法保證每秒60幀,導致屏幕畫面撕裂;
二、UI卡頓常見原因分析以及處理方案
1、過度繪制:
原因:界面布局設計不合理或者過於復雜導致系統無法在16毫秒內完成渲染,view過度繪制導致CPU或者GPU負載過重,View頻繁觸發measure、layout操作,導致measure、layout累計耗時嚴重以及整個View錯誤的頻隱讓繁重新渲染;
方案:優化界面布局,使界面布局視圖扁平化,去除不必要的背景顏色,減少透明色的使用;
方案依據原理:盡量減少View在系統中measure、layout、draw的累計時間;
2、UI線程的復雜運算
原因:UI主線程運算耗時
方案:減少UI線程中數據運算,使用子線程處理耗時任務
3、頻繁GC
原因:(1)、內存抖動;(2)、瞬間產生大量對象,消耗內存;
方案:盡量避免在循環邏輯或者onDraw方法中頻繁創建新對象和使用局部變數;
三、android Vsync機制
1、什麼是Vsync ?
Vsync 是Vertical Synchronization(垂直同步)的縮寫,是一種在PC上很早就廣泛使用的技術,可則慶以簡單的把它認為是一種定時中斷。而在Android 4.1(JB)中已經開始引入VSync機制,用來同步渲染,讓孫攜握AppUI和SurfaceFlinger可以按硬體產生的VSync節奏進行工作。
2、Android屏幕刷新過程
Android系統每隔16ms發出VSYNC信號,觸發對UI進行渲染,屏幕的刷新過程是每一行從左到右(行刷新,水平刷新,Horizontal Scanning),從上到下(屏幕刷新,垂直刷新,Vertical Scanning)。當整個屏幕刷新完畢,即一個垂直刷新周期完成,會有短暫的空白期,此時發出 VSync 信號。所以,VSync 中的 V 指的是垂直刷新中的垂直-Vertical。
3、沒有使用Vsync的情況
可見vsync信號沒有提醒CPU/GPU工作的情況下,在第一個16ms之內,一切正常。然而在第二個16ms之內,幾乎是在時間段的最後CPU才計算出了數據,交給了Graphics Driver,導致GPU也是在第二段的末尾時間才進行了繪制,整個動作延後到了第三段內。從而影響了下一個畫面的繪制。這時會出現Jank(閃爍,可以理解為卡頓或者停頓)。這時候CPU和GPU可能被其他操作佔用了,這就是卡頓出現的原因;
4、使用Vsync同步
CPU/GPU接收vsync信號,Vsync每16ms一次,那麼在每次發出Vsync命令時,CPU都會進行刷新的操作。也就是在每個16ms的第一時間,CPU就會響應Vsync的命令,來進行數據刷新的動作。CPU和GPU的刷新時間,和Display的FPS是一致的。因為只有到發出Vsync命令的時候,CPU和GPU才會進行刷新或顯示的動作。CPU/GPU接收vsync信號提前准備下一幀要顯示的內容,所以能夠及時准備好每一幀的數據,保證畫面的流暢;
5、多級緩沖
Android除了使用Vsync機制,還使用了多級緩沖的策略來優化屏幕顯示,如雙重緩沖(A + B),當Display buffer A 數據時,CPU/GPU就已經在buffer B 中處理下一幀要顯示的數據了。
可是,當系統資源緊張性能降低時,導致GPU在處理某幀數據時太耗時,在Vsync信號到來時,buffer B的數據還沒准備好,此時不得不顯示buffer A的數據,這樣導致後面CPU/GPU沒有新的buffer准備數據,空白時間無事可做,後面Jank頻出
因此採用三級緩沖來解決系統對性能不穩定導致的卡頓
當出現上面所述情況後,新增一個buffer C 可以減少CPU和GPU在Vsync同步間的空白間隙,此時CPU/GPU能夠利用buffer C 繼續工作,後面buffer A 和 buffer B 依次處理下一幀數據。這樣僅是產生了一個Jank,可以忽略不計,以後的流程就順暢了。
註:在多數正常情況下還是使用二級緩沖機制,三級緩沖只是在需要的時候才使用;
『貳』 Android流暢度評估及卡頓優化
Google定義:界面呈現是指從應用生成幀並將其顯示在屏幕上的動作。要確保用戶能夠流暢地與應用互動,應用呈現每幀的時間不應超過16ms,以達到每秒60幀的呈現速度(為什麼是60fps?)。
如果應用存在界面呈現緩慢的問題,系統會不得不跳過一些幀,這會導致用戶感覺應用不流暢,我們將這種情況稱為卡頓。
來源於: Google Android的為什麼是60fps?
16ms意味著1000/60hz,相當於60fps。這是因為人眼與大腦之間的協作無法感知超過60fps的畫面更新。12fps大概類似手動快速翻動書籍的幀率, 這明顯是可以感知到不夠順滑的。24fps使得人眼感知的是連續線性的運動,這其實是歸功於運動模糊的效果。 24fps是電影膠圈通常使用的幀率,因為這個幀率已經足夠支撐大部分電影畫面需要表達的內容,同時能夠最大的減少費用支出。 但是低於30fps是 無法順暢表現絢麗的畫面內容的,此時就需要用到60fps來達到想要的效果,超過60fps就沒有必要了。如果我們的應用沒有在16ms內完成屏幕刷新的全部邏輯操作,就會發生卡頓。
首先要了解Android顯示1幀圖像,所經歷的完整過程。
如圖所示,屏幕顯示1幀圖像需要經歷5個步驟:
常見的丟幀情況: 渲染期間可能出現的情況,渲染大於16ms和小於16ms的情況:
上圖中應該繪制 4 幀數據 , 但是實際上只繪制了 3 幀 , 實際幀率少了一幀
判斷APP是否出現卡頓,我們從通用應用和游戲兩個緯度的代表公司標准來看,即Google的Android vitals性能指標和地球第一游戲大廠騰訊的PrefDog性能指標。
以Google Vitals的卡頓描述為准,即呈現速度緩慢和幀凍結兩個維度判斷:
PerfDog Jank計算方法:
幀率FPS高並不能反映流暢或不卡頓。比如:FPS為50幀,前200ms渲染一幀,後800ms渲染49幀,雖然幀率50,但依然覺得非常卡頓。同時幀率FPS低,並不代表卡頓,比如無卡頓時均勻FPS為15幀。所以平均幀率FPS與卡頓無任何直接關系)
當了解卡頓的標准以及渲染原理之後,可以得出結論,只有丟幀情況才能准確判斷是否卡頓。
mpsys 是一種在設備上運行並轉儲需要關注的系統服務狀態信息的 Android 工具。通過向 mpsys 傳遞 gfxinfo 命令,可以提供 logcat 格式的輸出,其中包含與錄制階段發生的動畫幀相關的性能信息。
藉助 Android 6.0(API 級別 23),該命令可將在整個進程生命周期中收集的幀數據的聚合分析輸出到 logcat。例如:
這些總體統計信息可以得到期間的FPS、Jank比例、各類渲染異常數量統計。
命令 adb shell mpsys gfxinfo <PACKAGE_NAME> framestats 可提供最近120個幀中,渲染各階段帶有納秒時間戳的幀時間信息。
關鍵參數說明:
通過gfxinfo輸出的幀信息,通過定時reset和列印幀信息,可以得到FPS(幀數/列印間隔時間)、丟幀比例((janky_frames / total_frames_rendered)*100 %)、是否有幀凍結(幀耗時>700ms)。
根據第2部分的通用應用卡頓標准,可以通過丟幀比例和幀凍結數量,准確判斷當前場景是否卡頓。並且通過定時截圖,還可以根據截圖定位卡頓的具體場景。
如上圖所示,利用gfxinfo開發的檢查卡頓的小工具,圖中參數和卡頓說明如下:
根據上面對gfxinfo的幀信息解析,可以准確計算出每一幀的耗時。從而可以開發出滿足騰訊PerfDog中關於普通卡頓和嚴重卡頓的判斷。
依賴定時截圖,即可准確定位卡頓場景。如下圖所示(此處以PerfDog截圖示例):
通過第3部分的卡頓評估方法,我們可以定位到卡頓場景,但是如何定位到具體卡頓原因呢。
首先了解卡頓問題定位工具,然後再了解常見的卡頓原因,即可通過復現卡頓場景的同時,用工具去定位具體卡頓問題。
重點就是,充分利用gfxinfo輸出的幀信息,對卡頓問題進行分類。
了解了高效定位卡頓的方法和卡頓問題定位工具,再熟悉一下常見的卡頓原因,可以更熟練的定位和優化卡頓。
SurfaceFlinger 負責 Surface 的合成,一旦 SurfaceFlinger 主線程調用超時,就會產生掉幀。
SurfaceFlinger 主線程耗時會也會導致 hwc service 和 crtc 不能及時完成,也會阻塞應用的 binder 調用,如 dequeueBuffer、queueBuffer 等。
後台進程活動太多,會導致系統非常繁忙,cpu io memory 等資源都會被佔用,這時候很容易出現卡頓問題,這也是系統這邊經常會碰到的問題。
mpsys cpuinfo 可以查看一段時間內 cpu 的使用情況:
當線程為 Runnable 狀態的時候,調度器如果遲遲不能對齊進行調度,那麼就會產生長時間的 Runnable 線程狀態,導致錯過 Vsync 而產生流暢性問題。
system_server 的 AMS 鎖和 WMS 鎖 , 在系統異常的情況下 , 會變得非常嚴重 , 如下圖所示 , 許多系統的關鍵任務都被阻塞 , 等待鎖的釋放 , 這時候如果有 App 發來的 Binder 請求帶鎖 , 那麼也會進入等待狀態 , 這時候 App 就會產生性能問題 ; 如果此時做 Window 動畫 , 那麼 system_server 的這些鎖也會導致窗口動畫卡頓。
Android P 修改了 Layer 的計算方法 , 把這部分放到了 SurfaceFlinger 主線程去執行, 如果後台 Layer 過多,就會導致 SurfaceFlinger 在執行 rebuildLayerStacks 的時候耗時 , 導致 SurfaceFlinger 主線程執行時間過長。
主線程執行 Input Animation Measure Layout Draw decodeBitmap 等操作超時都會導致卡頓 。
Activity resume 的時候, 與 AMS 通信要持有 AMS 鎖, 這時候如果碰到後台比較繁忙的時候, 等鎖操作就會比較耗時, 導致部分場景因為這個卡頓, 比如多任務手勢操作。
應用裡面涉及到 WebView 的時候, 如果頁面比較復雜, WebView 的性能就會比較差, 從而造成卡頓。
如果屏幕幀率和系統的 fps 不相符 , 那麼有可能會導致畫面不是那麼順暢. 比如使用 90 Hz 的屏幕搭配 60 fps 的動畫。
由上面的分析可知對象分配、垃圾回收(GC)、線程調度以及Binder調用 是Android系統中常見的卡頓原因,因此卡頓優化主要以下幾種方法,更多的要結合具體的應用來進行:
在計算機和通信領域,幀是一個包括「幀同步串列」的數字數據傳輸單元或數字數據包。
在視頻領域,電影、電視、數字視頻等可視為隨時間連續變換的許多張畫面,其中幀是指每一張畫面。
『叄』 如何測試安卓(Android)系統的流暢度
測試方法一:系統自帶-開發者模式
實際上,為了方便開發者測試,安卓本身就內置了流暢度檢測的功能。不過,這需要我們開啟隱藏的開發者選項。如果你在用原生系統,那麼開啟開發者選項的方法很簡單,進入到設置菜單「關於手機」頁面,點擊數次「版本號」,即可開啟開發者選項。如果用的是其他ROM,方法也許有所不同,比如說魅族的Flyme開啟開發者選項的方法是在撥號界面輸入「*#*#6961#*#*」,其他機器方法也各有不同,大家可以參照廠商的說明。
進入到開發者選項,可以看到有「GPU呈現模式分析」的選項,開啟後即可以條形圖和線形圖的方法顯示系統的界面響應速度,可以用以觀察系統流暢度。那麼要如何根據曲線判斷系統是否流暢呢?實際上這個曲線表達的是GPU繪制每一幀界面的時間,只要不超過頂部綠線,都可以視為足夠流暢。
開啟GPU呈現模式分析
FPS Meter可以顯示最大最小幀數以及平均幀數
FPS Meter可以測試界面幀數,不過某些手機如果界面靜止,幀數會為0。FPS Meter除了測量系統界面幀數外,還可以用來測量游戲的幀數,所以用FPS Meter來測試某部安卓機游戲性能多強也是個很好的選擇。
當然,FPS Meter也並非十全十美。由於屬於第三方App,所以可能會有一些兼容性問題。某些安卓機或者ROM使用FPS Meter可能會不兼容,即使成功開啟了幀數顯示也沒法測量到准確數值,而某些設備使用FPS Meter甚至會死機。不過在大多數情況下,這款App還是相當值得信任的。
安卓在多個版本中都通過新技術提升了流暢度,比如說安卓2.3引入Dalvik、安卓4.0引入GPU界面繪制、安卓4.1引入黃油計劃、安卓4.3引入Trim以及安卓4.4引入ART等等。
H5頁面載入速度:window.performance.timing
Android以上測試方法不適用h5頁面
如何分析頁面整體載入速度:
主要是查看指標值PAGET_頁面載入時間,此指標指的是頁面整體載入時間但不含(onload事件和redirect), 此指標值可直接反應用戶體驗, 從此項指標可以知道指定某時間段的頁面載入速度值,以及和天,周,月的對比狀況.也可以查詢指標ALLT_頁面完全載入時間, 可以查詢到從瀏覽器開始導航(用戶點擊鏈接或在地址欄輸入url或點刷新,後退按鈕)到頁面onload 事件js完全跑完的所有時間.如果發現頁面載入速度有增加或減少,則可以分項查詢前面表格中的每個指標值,總的來說他們的關系如下:
dom開始載入前所有花費時間=重定向時間+域名解析時間+建立連接花費時間+請求花費時間+接收數據花費時間
pageLoadTime頁面載入時間=域名解析時間+建立連接花費時間+請求花費時間+接收數據花費時間+解析dom花費時間+載入dom花費時間
allLoadTime頁面完全載入時間=重定向時間+域名解析時間+建立連接花費時間+請求花費時間+接收數據花費時間+解析dom花費時間+載入dom花費時間+執行onload事件花費時間
resourcesLoadedTime資源載入時間=解析dom花費時間+載入dom花費時間
流暢度暫時沒有發現好用的測試衡量工具,開發層面了解,主要是根據log分析