01 | App啟動性能分析
基本的測試checklist和手段
專項測試(用戶維度)
- 崩潰(Crash,弱網)
- 卡頓(掉幀,gc,cpu)
- 響應慢(啟動時間,交互響應,H5加載)
- 發熱(cpu,mem,io,network,gps等硬件使用)
- 掉電快(硬件占用)
- 兼容性問題(機型覆蓋,回歸)
專項測試(技術維度)
- 崩潰(自動遍歷,monkey測試,橫豎屏切換,快速進退)
- 卡頓(卡頓測試,內存泄漏測試,method profile)
- 響應慢(冷仍啟動,界面切換,h5性能測試)
- 發熱(method profile,gc統計,io統計,流量統計,硬件使用統計,耗電量分析)
- 兼容性問題(兼容性測試,自動化測試,自動遍歷,monkey測試)
app性能
- android應有由很多的activity組成,這些activity的耦合度比較低
-
activity的啟動流程
image.png - 主要流程
1.Application OnCreate(加載第三方的sdk等)
2.Activity OnCreate(加載自身邏輯,發送遠程數據請求,渲染界面List)
app啟動性能指標
- 冷啟動(進程已被kill,或新安裝的應用)建議小于5s
- 暖啟動(app在后臺久了,會被內存管理kill,此時用戶重啟應用),建議小于2s
- 熱啟動(app在后臺運行),建議小于1.5s
- 首屏啟動(加上了stuff時間)
測試工具和方法
- adb logcat
- 錄屏+視頻拆幀:把1s拆成10幀,人工數幀,可以計算首屏啟動時間
- uiautomator等自動化工具,每隔200ms打印page_source的變化
- traceview:android的分析工具
- 硬埋點:最準確,app啟動前后植入埋點,再把數據回傳到服務器,需開發配合,不常用
adb logcat 使用
package=com.xueqiu.android
-
adb shell pm clear $package
清除緩存 -
adb shell am force-stop $package
停止進程 -
adb shell am start -S -W $package/.view.WelcomeActivityAlias
啟動app -
adb logcat | grep -i displayed
獲取數據
adb logcat結果
- startTime:記錄剛準備調用startActivityAndWait()的時間點
- endTime:記錄startActivityAndWait()函數調用返回的時間點
- WaitTime:startActivityAndWait()調用耗時(endTime - startTime)
- TotalTime:創建進程+創建object+創建activity的時間
使用ffmpeg拆幀
adb shell am force-stop $package
adb shell screenrecord --bugreport --time-limit 30 /data/local/tmp/xueqiu.mp4 &
adb shell am start -S -W $package/.view.WelcomeActivityAlias # 或手動點擊
adb pull /data/local/tmp/xueqiu.mp4 .
ffmpeg -i xueqiu.mp4 xueqiu.gif
ffmpeg -i xueqiu.mp4 -r 10 frames_%03d.jpg
02 | 接口性能
工具
- 代理工具:charles,burpsuite
1.電腦的流量都會經過charles,再到服務器
2.抓到請回和返回數據的內容 - 抓包工具:tcpdump,wireshark
1.主動請求服務器,抓取服務器返回的數據包
2.監聽端口,抓取發送和返回的數據包
03 | webview性能分析
簡介
- WebView是android中一個非常重要的控件,它的作用是用來展示一個web頁面。它使用的內核是webkit引擎,4.4版本之后,直接使用Chrome作為內置網頁瀏覽器。
chrome檢查中的關鍵選項
- Disable cache:不加載緩存,從零載入
- 藍色線:dom出現
-
紅色線:圖片等資源已加載完
image.png - timing各字段:
1.waiting:服務器響應時間
https://cloud.tencent.com/developer/article/1083690
手機瀏覽器性能分析
04 | H5性能分析
參考資料
-
https://www.w3.org/TR/navigation-timing/
image.png
資源加載指標
- prompt for unload:訪問新頁面時,舊頁面卸載完成時間
- redirect:重定向,用戶注銷登錄返回主頁面或跳轉到其他網站
- app cache:檢查緩存是否打開
- DNS:DNS查詢時間,若是長連接或請求文件來自緩存等本地存儲則返回fetchStart時間點
- TCP:與服務器建立連接的時間
- request:瀏覽器發起請求的時間
- response:拿到第一個響應字節到最后一個響應字節的時間
- processing:各種狀態的時間點
- load:觸發load事件執行時間
獲取單個資源的性能
瀏覽器 -> console -> PerformanceTiming
自動化獲取性能指標
- chrome -> console :
1.window.performance.timing
2.window.performance.timing.responseEnd - window.performance.timing.responseStart
- python代碼
from selenium import webdriver
class TestPerformance():
def test_performance(self):
driver = webdriver.Chrome()
driver.get("http://www.baidu.com")
print(driver.execute_script("return JSON.stringify(window.performance.timing)"))
05 | CPU統計
CPU與GPU的關系
- 圖形api不允許CPU直接與GPU通信
- 通過中間層鏈接CPU和GPU
- 中間層維護一個隊列
- CPU把display list放入隊列
-
GPU從隊列取數據進行繪制
image.png
image.png
GPU渲染工具
- android開發者模式提供性能調優工具:開發者選項 - GPU呈現模式分析 - 在屏幕上顯示為條形圖
GPR顯示內容
- 繪制每一幀所消耗的時間
- 不同顏色代表UI繪制的不同階段
1.官方資料:https://developer.android.com/topic/performance/rendering/inspect-gpu-rendering - 柱狀圖的中間有一根綠色的橫線,代表16ms繪制時間基準
- GRP會統計并顯示app最近運行的128幀
06 | mem統計
名詞解釋
名詞術語 | 全拼 | 解釋 |
---|---|---|
VSS | virtual set size | 虛擬內存(包含共享庫占用的內存) |
RSS | resident set size | 實際使用的物理內存(包含共享庫占用的內存) |
PSS | proportional set size | 實際使用的物理內存(比例分配共享占用內存) |
USS | unique set size | 進程獨自占用的物理內存(不包含共享庫占用的內存) |
各指標解析
VSS:衡量虛擬內存大小無太大用處,無法知道分配物理內存大小
RSS:各進程的RSS相加,會超過系統內存使用量
PSS:各進程的RSS相加,就是系統內存使用量
USS:是PSS中自己的部分,不包含任何共享部分
procstats
adb shell dumpsys procstats --hours 3
adb shell dumpsys meminfo com.xueqiu.android
輸出詳解
- 進程詳情
1.進程名稱/user/versionCode
2.狀態:minPSS-avgPSS-maxPSS/minUSS-avgUSS-maxUSS - 100%:表示在總的時間內,進程在各種狀態下的消耗(100%即在這段時間,進程一直處于運行當中)
- total:表示進程的綜合占用情況
- Imp Fg:加載到前臺
- Service:標識是否是服務
- Persisitent:標識是否一直駐留在內存,與service一樣表示內存進駐的級別
- Top:標識是否是頂層進程
- Receiver:標識是否是廣播進程
補充
同一時間有多個應用占用內存,測內存要對比不同版本的內存大小
07 | 網絡流量分析
顯示網路流量
adb shell dumpsys netstats
找到應用UID
adb shell dumpsys package com.xueqiu.android | grep userId
-
adb shell dumpsys netstats | grep 10051
1.rb:receive byte
2.rp:receiver package
3.tb:transport byte
4.tp:transport package
08 | 卡頓分析
cpu、網絡、內存都有可能引起卡頓
systrace
- sdk/platform-tools/systrace
- 須python2.7
運行中遇到的問題
- 提示"No module win32com"
解決:pip2 install pypiwin32
- 提示"No module six"
解決:pip2 install six
使用
cd D:\Programs\android-sdk-windows\platform-tools\systrace
-
python systrace.py -e 設備 -l
進入錄制模式,在設備上操作,命令行按下enter結束錄制,并在systrace目錄下生成result
查看報告
- 藍點:警告
- cpu
- 指定app
- 綠色圓點:代表每一幀,點擊綠色圓點,按M鍵顯示加載時間
- 函數調用
- 任務狀態:灰-休眠,藍-可運行,綠-運行,橙-不響應
- 常用命令:w-放大,s-縮小,m-找到下一幀,顯示時間
卡頓影響因素
- 內存問題(內存抖動,垃圾回收)
- cpu(計算耗時)
- render(布局復雜,overdraw)
幀分析
- 冰凍幀:一個幀超過0.7s
09 | 耗電量測試
應用耗電過大,導致手機過熱,cpu降頻。耗電量測試就是通過不同的測試場景,找出app高耗電的場景并解決
安裝
- golang
- python 2.7
git clone https://github.com/google/battery-historian.git
go get -d -u github.com/google/battery-historian/...
- 修改setup.go中的closureCompilerVersion="20190513"
go run setup.go
go run cmd/battery-historian/battery-historian.go
batterystats收集數據
- 清理耗電量數據
adb shell dumpsys batterystats --reset
adb shell dumpsys batterystats --enable full-wake-history
- 運行測試用例或手動操作
- 收集數據
1.android 7.0及以上:adb bugreport bugreport.zip
2.android 6.0:adb bugreport > bugreport.txt - 上傳數據
1.打開localhost:9999
2.把zip或txt上傳
查看報告
- 指標含義
1.battery_level:電量
2.plugged:充電狀態及充電時長
3.screen:屏幕是否點亮
4.top:顯示當前手機運行的app
5.status:電池狀態信息,充電、放點、未充電、已充滿、未知等
10 | 健壯性測試
測試系統在出現故障時,能否自動恢復或忽略故障繼續運行
操作過程
- 對應用進行盲點
- 網絡不佳
- 數據不通
使用工具
- Monkey,Maxim,Charles,Appcrawler
11 | 弱網測試
弱網問題
- 封閉環境,網速降低
1.掉包
2.數據無法加載
3.消息更新不及時
弱網速度
- 低于2G速率
- 3G
模擬弱網
-
charles代理設置
image.png -
設置本地代理
image.png - 開啟節流(Proxy-Throttle Setting -Enable Throttling)
名詞解釋
- Bandwidth(帶寬:理論網速上限)
1.上行:數據流出,如上傳
2.下行:數據流入,如下載
3.帶寬的單位是Mbps,真實的網速要除以8,如帶寬是10M,真實網速最高可達到1.25M - Round-trip Latency(請求往返延遲)
1.客戶端與服務器第一次往返通信的延遲,單位毫秒 - MTU(最大傳輸單元)
1.傳輸的TCP數據包的最大尺寸 - Reliability(可靠性)
1.衡量連接完全失敗的可能性,如為50%,則只有50%的成功率
12 | 實戰1
非功能測試(針對專項質量問題的測試)
- 移動端性能問題(硬件相關,如cpu、mem、disk、network、gpu)
- 移動端場景問題(場景相關,如弱網測試、兼容性測試、國際化)
常用的測試方案
- android
1.ddms
2.android studio最新版本的集成工具
3.hook
4.代碼插樁 - IOS
1.instruments
2.hook
3.代碼插樁
app啟動性能指標
- 首次安裝啟動:會耗費較多時間初始化,如下載補丁、緩存數據
- 冷啟動:進程不存在(主要關注,不超過5秒)
- 暖啟動:進程存在,界面不存在
- 熱啟動:界面對象依然存在,只是從后臺切到前臺
- 首屏啟動:第一屏加載完成
測試啟app動性能的方法
- logcat觀察啟動時間
- 錄屏拆幀
- 注:通常殺掉進程,不清理數據
web性能
https://developers.google.com/web/tools/chrome-devtools/network/reference#timing-explanation
13 | 實戰2
chrome中network的使用
- 藍線:dom 加載完成
- 紅線:所有資源加載完成
- 捕獲:查看加載圖片
- 根據 waterfall 排序 ,進行資源篩選
- shift 查看資源依賴關系
chrome模擬手機
- setting-devices,勾選手機
chromer中performance的使用
- record button
- screenshorts
- Diable JavaScript samples 禁用js樣例,禁用后調用關系簡單很多
-
Enable advanced paint instrumentation
image.png
appium性能獲取
from appium import webdriver
from selenium.webdriver.common.by import By
class TestWebview:
_package = "com.xueqiu.android"
_activity = ".view.WelcomeActivityAlias"
def test_webview(self):
caps = dict()
caps["platformName"] = "android"
caps["deviceName"] = "hogwarts"
caps["appPackage"] = self._package
caps["appActivity"] = self._activity
caps["noReset"] = True
# 需要對應版本的 chromedirver ,才能在 webview 中執行 js 代碼
caps["chromedriverExecutable"] = "C:/develop/chromedriver/chromedriver2.20.exe"
# 初始化driver
self._driver = webdriver.Remote(
"http://localhost:4723/wd/hub",
caps)
self._driver.implicitly_wait(15)
# 進入到 webview
self._driver.find_element(By.XPATH, "http://*[@text='交易']").click()
# 切換上下文到 webview
webview = self._driver.contexts[-1]
self._driver.switch_to.context(webview)
# 執行 js 代碼,獲取性能數據
all_time = self._driver.execute_script("return window.performance.timing")
# 對數據進行二次操作
response_time = all_time['responseEnd'] - all_time['responseStart']
print(response_time)
使用adb shell 獲取cpu的使用率
while true;do adb shell top -n 1 | grep xueqiu | awk '{print $3}';done
14 | 實戰3
https://www.w3.org/TR/navigation-timing/#performancenavigation
navigation
TYPE_NAVIGATE = 0
TYPE_RELOAD = 1
TYPE_BACK_FORWARD = 2
-
window.performance.navigation.type
新打開頁面,type的初始值是0,隨著頁面操作,type的值隨之變化;如刷新頁面,type的值變為1
使用js模擬瀏覽器動作
window.history.back()
window.history.forward()
window.location.reload()
window.location.href=“https://www.baidu.com/"
window.location.href # 獲取當前網址
將手機內容下載到本地
adb pull ///data/user/0/com.xueqiu.android/files/h5/modules_new/xueqiu.com ~/Desktop/xueqiu.com
查看webview網址
adb logcat | grep http
adb logcat -c
清除logcat
喚醒鎖
https://developer.android.google.cn/topic/performance/vitals?hl=en
- 喚醒鎖阻止設備進入睡眠模式,若喚醒鎖不釋放,耗電量會很高
-
adb shell dumpsys power
查看喚醒鎖
image.png - 避免使用喚醒鎖
https://developer.android.google.cn/guide/background - 喚醒鎖改進:使用前臺服務
https://developer.android.google.cn/guide/components/services#Foreground
Amdahl定律
- S:加速比
- a:系統某部分所需時間與總時間的比例
-
k:性能提升比例
image.png
image.png
Amdahl特殊情況
-
考慮k->無窮
image.png