當前狀況
- 安裝低端機型H5頁面可能存在丟幀問題
丟幀卡頓可能原因分析
現象分析
- 呈現速度緩慢: 在呈現速度緩慢的幀數較多的頁面,當超過50%的幀呈現時間超過16ms毫秒時,用戶感官明顯卡頓。
- 幀凍結的繪製耗時超過700ms,爲嚴重卡頓問題。
- 卡頓忽略FPS<=2的頁面:因爲人的視覺暫留100400ms,即FPS在2.510之間時,所以當FPS低於3時,人眼看到的並不是連續動作,即使有丟幀現象,也不會察覺。
具體問題分析
- 當前程序運行CPU運行過高
- 當前程序運行內存佔用過高
定位問題
當前情況分析
- 使用Android官方提供的dumpsys工具進行分析
- 執行:
adb shell dumpsys gfxinfo com.sohu.newsclient
- 詳細正文數據分析
- 執行:
Stats since: 29087419659040ns
Total frames rendered: 1771 : 本次dump收集了1771幀信息
Janky frames: 776 (43.82%) : 1711幀中有776幀超過16ms, 卡頓概率爲: 43.8%
50th percentile: 14ms
90th percentile: 28ms
95th percentile: 57ms
99th percentile: 350ms
Number Missed Vsync: 60 : 垂直同步失敗的幀
Number High input latency: 1533 : 處理input超市的幀
Number Slow UI thread: 96 : 因UI線程上的工作導致超時值
Number Slow bitmap uploads: 1 : 因bitmap的加載耗時的幀數
Number Slow issue draw commands: 77 : 因繪製導致耗時的幀數
Number Frame deadline missed: 120
-
Janky frames 並不代表用戶視覺上的,顯示在屏幕上的丟幀率,但是它可以代表有問題的幀率.
-
通過安卓組掉幀工具分析
- 可通過掉幀發生時, 具體的執行函數情況分析
- 結果: 未發現在安卓掉幀過程中有webview函數執行
內存情況分析
分析真實內存情況
- 使用Android中自帶的Profile工具內存分析
正常打開正文頁, 在低端手機中運行情況分析
- 數據發現:
- app heap:佔用大部分內存
- image heap: 照用一部分內存
- 在app heap中"com.baidu.mobads.container.util.b"佔用了大部分的內存
- 經過山總查證, 次部分是廣告佔用了大部分內存.
- 仔細論證內存佔用關係:
- 正文頁運行佔用內存分別如下
- Total: 373.M
- Java: 38.7M - Java堆內存的使用量。Java堆是Java虛擬機中用於存儲對象實例的一部分內存空間
- Native: 103.M - 應用程序通過本地方法(Native Method)分配的內存量。本地方法是使用C、C++或其他本地語言編寫的代碼,在Android開發中,通常用來執行一些高性能或者系統相關的操作。
- Graphics: 109.7M - 用於繪製圖形和UI元素的內存量。包括位圖、畫布等圖形相關的資源。
- Stack: 7.3M - 程序的調用堆棧(Call Stack)所佔用的內存量。調用堆棧用於跟蹤當前執行線程的方法調用順序。
- Code: 53.2M - 應用程序加載的代碼的內存量。包括應用程序的可執行代碼、庫文件和其他相關的代碼資源。
- Other: 61.2M - 包括一些不容易歸類的內存分配,例如一些系統資源、緩存或者其他一些不屬於前述類別的內存使用情況。
- 結論: Native中的運行佔用的大部分內存
- 對比空正文頁面運行結果
-
- Total: 348.5M
- Java: 37M
- Native: 126M
- Graphics: 49.8M
- Stack: 6.8M
- Code: 48.5M
- Others: 80.3M
- 對比結論: 正文和推薦專題, 渲染評論等佔用內存: 大概50M作用.
正文內存查看
- 正文正常加載內存
- 頁面佔用內存7.4M
- 去掉正文加載內存
- 頁面佔用1.8M
- 結論: H5佔用內存內存爲5.5M左右
滾動時內存變換
- 滾動時內存變化來自GPU渲染佔用的內存變化
結論
- 正文H5頁面渲染, 大概佔用內存30M作用
- 正文H5頁面正文部分運行佔用內存5M作用
- H5未佔用大量內存, 建議: 每次合板後, 檢測H5佔用內存
網絡資料卡頓優化建議
- 參考: Android流暢度評估及卡頓優化
- 對象分配、垃圾回收(GC)、線程調度以及Binder調用 是Android系統中常見的卡頓原因
- 佈局優化
- 通過減少冗餘或者嵌套佈局來降低視圖層次結構。比如使用約束佈局代替線性佈局和相對佈局。
- 用 ViewStub 替代在啓動過程中不需要顯示的 UI 控件。
- 使用自定義 View 替代複雜的 View 疊加。
- 減少嵌套層次和控件個數。
- 使用Tags:Merge標籤減少佈局嵌套層次,ViewStub標籤推遲創建對象、延遲初始化、節省內存等。
- 減少過度繪製
- 減少主線程耗時操作
- 主線程中不要直接操作數據庫,數據庫的操作應該放在數據庫線程中完成。
- sharepreference儘量使用apply,少使用commit,可以使用MMKV框架來代替sharepreference。
- 網絡請求回來的數據解析儘量放在子線程中,不要在主線程中進行復制的數據解析操作。
- 不要在activity的onResume和onCreate中進行耗時操作,比如大量的計算等。
- 列表優化
- RecyclerView使用優化,使用DiffUtil和notifyItemDataSetChanged進行局部更新等。
- 內存優化
- 減少小對象的頻繁分配和回收操作。
- 被頻繁調用的緊密的循環裏,避免對象分配來降低GC的壓力。