我們在使用各種 App 的時候基本會關注到:這款軟件挺耗流量的?運行起來設備掉電有點快嘛?切換頁面的時候還會有卡頓等現象?如果遇到有這些問題的 App 我們基本會將它請出我們的愛機。由此可見軟件是否受歡迎除了提供必要的功能外,流暢性、流量/電池消耗也是很重要的指標。
今天就來從我們測試人員的角度,談一談 App 驗收測試過程中需要關注到一些指標項目:
內存占用
CPU 占用
流量耗用
電量耗用
啟動時間
因為最近就著騰訊 TMQ 團隊出版的《移動 App 性能評測與優化》這本書在看 App 性能測試這一塊的東西,看著看著發現有些名詞或者概念不是很明白,所以在看這塊東西的時候,還要一邊去查詢一些其他的點,現在將這些點記錄下來,也算是一篇讀書筆記了吧,下面針對每一個方面的一些重要知識點進行了整理。
說到內存方面,最經典的內存問題當數內存泄漏。百度上對內存泄漏的定義是這樣的:內存泄漏(Memory Leak)是指程序中己動態分配的堆內存由于某種原因程序未釋放或無法釋放,造成系統內存的浪費,導致程序運行速度減慢甚至系統崩潰等嚴重后果。通俗點講,在大部分應用中,會有一類功能是需要加載附加資源的,比如顯示從網絡下載的文本或圖片。這類功能往往需要在內存中存放要使用的資源對象,退出該功能后,就需要將這些資源對象清空。如果忘了清理,或者是代碼原因造成的清理無效,就會形成內存泄漏。
說到了內存泄漏,又不得不提到垃圾回收(Garbage Collector,簡稱 GC),內存中的垃圾,主要指的是內存中已無效但又無法自動釋放的空間,除非是重啟系統不然永遠也不會還給操作系統。這樣以來,時間久了當程序運行的時候就會產生很多垃圾,一方面浪費了不少內存空間,另一方面如果同一個內存地址被刪除兩次的話,程序就會不穩定,甚至奔潰。
在 Java 程序運行過程中,一個垃圾回收器會不定時地被喚起檢查是否有不再被使用的對象,并釋放它們占用的內存空間。但垃圾回收器的回收是隨機的,可能在程序的運行的過程中,一次也沒有啟動,也可能啟動很多次,它并不會因為程序一產生垃圾,就馬上被喚起而自動回收垃圾。所以垃圾回收也并不能完全避免內存泄漏的問題。
另一方面,垃圾回收也會給系統資源帶來額外的負擔和時空開銷。它被啟動的幾率越小,帶來的負擔的幾率就越小。
內存指標有 VSS、RSS、PSS、USS,他們的含義分別是:
VSS:Virtual Set Size 虛擬耗用內存(包含共享庫占用的內存)
RSS:Resident Set Size 實際使用物理內存(包含共享庫占用的內存)
PSS:Proportional Set Size 實際使用的物理內存(按比例分配共享庫占用的內存)
USS:Unique Set Size 進程獨自占用的物理內存(不包含共享庫占用的內存)
一般來說內存占用大小有如下規律:VSS >= RSS >= PSS >= USS,一般測試中關注的比較多的是 PSS 這個指標。
以下是幾種常見的內存分析工具,具體使用方法這里就不詳述了。
該工具位于 Android Monitor 下面,Android Monitor 是 Android Studio 自帶的一個強大的性能分析工具,里面一共包含 5 個模塊:Logcat、Memory、CPU、Network 及 GPU。
Memory Monitor 可以實時查看 App 的內存分配情況,判斷 App 是否由于 GC 操作造成卡頓以及判斷 App 的 Crash 是否是因為超出了內存。
該內存檢測工具位于 DDMS 下面,在 Android Studio 里面可以通過 Tools-Android-Android Device Monitor 打開,Heap Viewer 可以實時查看 App 分配的內存大小和空閑內存大小,并且發現 Memory Leaks。
MAT(Memory Analyzer Tool),是一個被老生常談的 Android 內存分析工具,它可以清楚的獲知整體內存使用情況。雖然是 Eclipse 的工具,但也可以單獨運行,不需要安裝 Eclipse。
時間片即 CPU 分配給各個程序的時間,每個線程被分配一個時間段,稱作它的時間片,即該進程允許運行的時間,使各個程序從表面上看是同時進行的。
要講 Jiffies 需要先提到這兩個概念:HZ 和 Tick
HZ:Linux 核心每隔固定周期會發出 timer interrupt (IRQ 0),HZ 是用來定義每一秒有幾次 timer interrupts。例如 HZ 為 1000,就代表每秒有 1000 次 timer interrupts。
Tick:HZ 的倒數,Tick = 1/HZ,即 timer interrupt 每發生一次中斷的時間。如 HZ 為 250 時,tick 為 4 毫秒(millisecond)。
而 Jiffies 為 Linux 核心變量,是一個 unsigned long 類型的變量,被用來記錄系統自開機以來,已經過了多少 tick。每發生一次 timer interrupt,Jiffies 變數會被加 1。
Linux 下使用命令 cat /proc/stat
,查看具體整機的 Jiffies,如圖:
Linux 下使用命令 cat /proc/<進程id>/stat
,查看具體某個進程的 Jiffies:
在 Linux 系統下,CPU 利用率分為用戶態、系統態和空閑態,他們分別代表的含義為:用戶態表示 CPU 處于用戶態執行的時間,系統態表示系統內核執行的時間,空閑態表示空閑系統進程執行的時間。
而一個 App 的 CPU 使用率 = CPU 執行非系統空閑進程時間 / CPU 總的執行時間,也可以表示為 App 用戶態 Jiffies + App 系統態 Jiffies / 手機總 Jiffies。
可能會使整個手機無法響應,整體性能降低,引起 ANR,導致手機更耗電,降低用戶體驗等。
我們的手機通過運營商的網絡訪問 Internet,運營商替我們的手機轉發數據報文,數據報文的總大?。ㄗ止潝担┘戳髁?,數據報文是包含手機上下行的報文。
主要是利用工具 Tcpdump 抓包,導出 pcap 文件,再在 wireshark 中打開進行分析。
利用 Android 自身提供的 TCP 收發長度的統計功能,獲取 App 的 tcp_snd 和 tcp_rcv 的值,測試一段時間后再分別統計一次,用 tcp_snd
兩者的差值得到發送流量,用 tcp_rcv 兩者的差值得到接受流量。
TrafficStats
Android 2.2 版本開始加入 android.net.TrafficStats 類來實現對流量統計的操作。
部分方法如下:
static long getMobileRxBytes() //獲取通過移動數據網絡收到的字節總數
static long getMobileTxBytes() //通過移動數據網發送的總字節數
static long getTotalRxBytes() //獲取設備總的接收字節數
static long getTotalTxBytes() //獲取設備總的發送字節數
static long getUidRxBytes(int uid) //獲取指定uid的接收字節數
static long getUidTxBytes(int uid) //獲取指定uid的發送字節數
NetworkStatsManager
Android 6.0 版本開始,為了打破了原本 TrafficStats 類的查詢限制,官方又提供了 NetworkStatsManager 類,可以獲取更精準的網絡歷史數據,也不再是設備重啟以來的數據。部分方法如下:
NetworkStats.Bucket querySummaryForDevice(int networkType, String subscriberId, long startTime, long endTime) // 查詢指定網絡類型在某時間間隔內的總的流量統計信息
NetworkStats queryDetailsForUid(int networkType, String subscriberId, long startTime, long endTime, int uid) // 查詢某uid在指定網絡類型和時間間隔內的流量統計信息
NetworkStats queryDetails(int networkType, String subscriberId, long startTime, long endTime) // 查詢指定網絡類型在某時間間隔內的詳細的流量統計信息(包括每個uid)
定位,尤其是調用 GPS 定位。
網絡傳輸,尤其是非 Wifi 環境。
屏幕亮度
CPU 頻率
內存調度頻度
wake_locker 時間和次數
其他傳感器
使用命令 adb shell dumpsys batterystats> batterystats.txt
可以打印出詳細的耗電相關信息并保存統計的電量信息到 batterystats.txt 這個文件里。
因為這個工具是 Go 語言開發,所以需要預裝Go語言開發環境,當然如果你不想配置Go語言環境,官方還提供了一種更方便的方案,通過安裝 docker 環境來使用這個工具。具體這個工具的配置安裝和具體使用方法以及參數的代表含義,我會單獨再寫一篇文章記錄,先拋磚引玉放一張這個工具的運行截圖。
當應用退到后臺運行時,盡量減少應用的主動運行,當檢測到 CPU 時間片消耗異常時,深入線程進行分析。
前臺運行時不要注冊 wake lock。
后臺運行時,在保證業務需要的前提下,應盡量減少注冊 wake lock。
降低對系統的喚醒頻率, 使用 partial wake lock 代替 wake lock。
合理設置 GPS 的使用時長和使用頻率。
考慮到用戶使用場景的多樣性,導致很難定位用戶異常耗電的根源,所以為了更深一層弄清楚這些問題,可以考慮定期上報灰度用戶手機電量數據的方式來分析問題。
可使用命令 adb shell am start -W packagename/activity
查看 App 啟動耗時,查看了一下我們自己的 App Android 版本的啟動耗時如下:
注釋:
WaitTime:總的耗時,包括前一個應用 Activity pause 的時間和新應用啟動的時間
ThisTime:一連串啟動 Activity 的最后一個 Activity 的啟動耗時
TotalTime:新應用啟動的耗時,包括新進程的啟動和 Activity 的啟動,但不包括前一個應用 Activity pause 的耗時
App性能問題會直接影響產品體驗:耗流量、掉電快、卡頓、崩潰等現象會給用戶造成不良的體驗和印象,不利于產品的活躍及用戶留存。許多經驗豐富的程序員也會經常忽視這些不起眼的性能問題,因此作為測試人員,在版本發布前及早關注并發現上述性能問題就顯得尤其重要。但真正做起App性能測試才發現這條路并不容易走,抓取內存、CPU 等一些項目的指標容易,但對一些數據的敏感度和處理方式都是要靠經驗的慢慢積累??傊?,性能測試算是一項比較繁瑣的工作,但難者不易,易者不難,希望已經行走在這條路上的或者準備踏上這條路的同行都能不斷提高自身素養,堅持到底。
原文轉自:https://mp.weixin.qq.com/s/qD39G0IxhqyT_Iekxte2lQ?utm_source=tuicool&utm_medium=referral