CPU測試
CPU跟內存一樣,存在一些測試子項,如下清單所示
1.空閑狀態下的應用CPU消耗情況
2.中等規格狀態下的應用CPU消耗情況
3.滿規格狀態下的應用CPU消耗情況
4.應用CPU峰值情況
CPU的測試方法分為幾類
1.使用android提供的adb shell dumpsys cpuinfo |grep packagename >/address/cpu.txt來獲取 ,要root
2.使用top命令 adb shell top |grep packagename>/address/cpu.txt 來獲取,要root
3. 使用adb shell cat /proc/stat 來獲取
CPUINFO 詳解:
/proc/stat文件
該文件包含了所有CPU活動的信息,該文件中的所有值都是從系統啟動開始累計到當前時刻。不同內核版本中該文件的格式可能不大一致,以下通過實例來說明數據該文件中各字段的含義。
實例數據:2.6.24-24版本上的
xxx-desktop:~$ cat /proc/stat
cpu 38082 627 27594 893908 12256 581 895 0 0
cpu0 22880 472 16855 430287 10617 576 661 0 0
cpu1 15202 154 10739 463620 1639 4 234 0 0
intr 120053 222 2686 0 1 1 0 5 0 3 0 0 0 47302 0 0 34194 29775 0 5019 845 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ctxt 1434984
btime 1252028243
processes 8113
procs_running 1
procs_blocked 0
第一行的數值表示的是CPU總的使用情況,所以我們只要用第一行的數字計算就可以了。下表解析第一行各數值的含義:
參數 解析(單位:jiffies)
(jiffies是內核中的一個全局變量,用來記錄自系統啟動一來產生的節拍數,在linux中,一個節拍大致可理解為操作系統進程調度的最小時間片,不同linux內核可能值有不同,通常在1ms到10ms之間)
user (38082) 從系統啟動開始累計到當前時刻,處於用戶態的運行時間,不包含 nice值為負進程。
nice (627) 從系統啟動開始累計到當前時刻,nice值為負的進程所占用的CPU時間
system (27594) 從系統啟動開始累計到當前時刻,處於核心態的運行時間
idle (893908) 從系統啟動開始累計到當前時刻,除IO等待時間以外的其它等待時間iowait (12256) 從系統啟動開始累計到當前時刻,IO等待時間(since 2.5.41)
irq (581) 從系統啟動開始累計到當前時刻,硬中斷時間(since 2.6.0-test4)
softirq (895) 從系統啟動開始累計到當前時刻,軟中斷時間(since 2.6.0-test4)stealstolen(0) which is the time spent in other operating systems when running in a virtualized environment(since 2.6.11)
guest(0) which is the time spent running a virtual CPU for guest operating systems under the control of the Linux kernel(since 2.6.24)
結論:總的cpu時間totalCpuTime = user + nice + system + idle + iowait + irq + softirq + stealstolen + guest
/proc/<pid>/stat文件
該文件包含了某一進程所有的活動的信息,該文件中的所有值都是從系統啟動開始累計
到當前時刻。以下通過實例數據來說明該文件中各字段的含義。
[xxx@buick ~]# cat /proc/6873/stat
6873 (a.out) R 6723 6873 6723 34819 6873 8388608 77 0 0 0 41958 31 0 0 25 0 3 0 5882654 1409024 56 4294967295 134512640 134513720 3215579040 0 2097798 0 0 0 0 0 0 0 17 0 0 0
說明:以下只解釋對我們計算Cpu使用率有用相關參數
參數 解釋
pid=6873 進程號
utime=1587 該任務在用戶態運行的時間,單位為jiffies
stime=41958 該任務在核心態運行的時間,單位為jiffies
cutime=0 所有已死線程在用戶態運行的時間,單位為jiffies
cstime=0 所有已死在核心態運行的時間,單位為jiffies
結論:進程的總Cpu時間processCpuTime = utime + stime + cutime + cstime,該值包括其所有線程的cpu時間。
參考代碼(python2.7):
class CpuProfiler(BaseProfiler): def __init__(self, pid, adb, loghd): BaseProfiler.__init__(self, adb) self.appPid = pid self.loghd = loghd self.processcpuRatioList = [] self.cpuRatioList = [] self.lastRecord = {} self.lastTime = 0 self.titile = ["應用占用CPU(%)", "總占用CPU(%)"] def init(self): processCpu = self.getprocessCpuStat() idleCpu, totalCpu = self.getTotalCpuStat() self.lastRecord["processCpu"] = processCpu self.lastRecord["idleCpu"] = idleCpu self.lastRecord["totalCpu"] = totalCpu self.lastTime = datetime.datetime.now() self.androidversion = self.getAndroidVersion()
def getprocessCpuStat(self): #print "self.appPid="+self.appPid stringBuffer = self.adb.cmd("shell", "cat", "/proc/" + str(self.appPid) + "/stat").communicate()[0].decode( "utf-8").strip() r = re.compile("\\s+") toks = r.split(stringBuffer) #想獲取的是process的cpu個數,procs_running +procs_blocked processCpu = float(long(toks[13]) + long(toks[14])); #print "processCpu=", processCpu return processCpu def getTotalCpuStat(self): child_out = self.adb.cmd("shell", "cat", "/proc/stat").communicate()[0].decode("utf-8").strip().split("\r\r\n")[ 0] if int(self.androidversion) >= 19: child_out = self.adb.cmd("shell", "cat", "/proc/stat", "|grep ^cpu\ ").communicate()[0].decode( "utf-8").strip() if " grep: not found" in child_out: child_out = \ self.adb.cmd("shell", "cat", "/proc/stat").communicate()[0].decode("utf-8").strip().split("\r\r\n")[ 0] r = re.compile(r'(?<!cpu)\d+') toks = r.findall(child_out) idleCpu = float(toks[3]) totalCpu = float(reduce(lambda x, y: long(x) + long(y), toks)); return idleCpu, totalCpu def profile(self): processCpu = self.getprocessCpuStat() idleCpu, totalCpu = self.getTotalCpuStat() currentTime = datetime.datetime.now() diffTime = currentTime - self.lastTime retry = False processcpuRatio = 100 * (processCpu - self.lastRecord["processCpu"]) / (totalCpu - self.lastRecord["totalCpu"]); cpuRatio = 100 * ((totalCpu - idleCpu) - (self.lastRecord["totalCpu"] - self.lastRecord["idleCpu"])) / ( totalCpu - self.lastRecord["totalCpu"]); if (diffTime.seconds * 1000 + diffTime.microseconds / 1000) < abs(totalCpu - self.lastRecord["totalCpu"]): self.loghd.info("cpu data abnormal, do again!") retry = True self.lastTime = currentTime self.lastRecord["processCpu"] = processCpu self.lastRecord["idleCpu"] = idleCpu self.lastRecord["totalCpu"] = totalCpu return round(float(processcpuRatio), 2), round(float(cpuRatio), 2), retry