Android CPU proc技术方法
1. proc/stat
该文件包含了所有CPU活动的信息,文件中的所有值都是从系统启动开始累计到当前时刻。
$ adb shell /proc/stat cpu
//CPU指标:user,nice, system, idle, iowait, irq, softirq
cpu 130216 19944 162525 1491240 3784 24749 17773 0 0 0
cpu0 40321 11452 49784 403099 2615 6076 6748 0 0 0
cpu1 26585 2425 36639 151166 404 2533 3541 0 0 0
cpu2 22555 2957 31482 152460 330 2236 2473 0 0 0
cpu3 15232 1243 20945 153740 303 1985 3432 0 0 0
cpu4 5903 595 6017 157410 30 10959 605 0 0 0
cpu5 4716 380 3794 157909 23 118 181 0 0 0
cpu6 8001 515 8995 157571 48 571 180 0 0 0
cpu7 6903 377 4869 157885 31 271 613 0 0 0
- user (130216) :从系统启动开始累计到当前时刻,用户态的CPU时间(单位:jiffies),不包含nice值为负的进程。
- nice(13295) :从系统启动开始累计到当前时刻,nice值为负的进程所占用的CPU时间(单位:jiffies)
- system(162525) :从系统启动开始累计到当前时刻,核心时间(单位:jiffies)
- idle(422145968) 从系统启动开始累计到当前时刻,除硬盘IO等待时间以外其它等待时间(单位:jiffies)
- iowait(171474): 从系统启动开始累计到当前时刻,硬盘IO等待时间(单位:jiffies)
- irq (233) 从系统启动开始累计到当前时刻,硬中断时间(单位:jiffies)
- softirq(5346) 从系统启动开始累计到当前时刻,软中断时间(单位:jiffies)
1 jiffies 约等于 10ms
totalCpuTime=user+system+nice+idle+iowait+irq+softirq
2. proc/[pid]>/stat
该文件包含了某一进程所有的活动的信息,该文件中的所有值都是从系统启动开始累计到当前时刻。
$ adb shell cat /proc/1557/stat
//CPU指标:utime、stime、cutime、cstime
1557 (system_server) S 823 823 0 0 -1 1077952832 //1~9
2085481 15248 2003 27 166114 129684 26 30 //10~17
10 -10 221 0 2284 2790821888 93087 18446744073709551615 //18~25
1 1 0 0 0 0 6660 0 36088 0 0 0 17 3 0 0 0 0 0 0 0 0 0 0 0 0 0
- pid: 进程ID,此处等于1557
- utime: 该进程处于用户态的时间,此处等于166114,单位jiffies
- stime: 该进程处于内核态的时间,此处等于129684,单位jiffies
- cutime: 当前进程等待子进程的utime, 此处等于26,单位jiffies
- cstime: 当前进程等待子进程的utime,此处等于30,单位jiffies
进程的总Cpu时间 processCpuTime = utime + stime+ cutime + cstime,(图中第14-17个数求和)该值包括其所有线程的cpu时间
3. 单核情况下Cpu使用率的计算
通过读取/proc/stat 、/proc/<pid>/stat、/proc/<pid>/task/<tid>/stat
以及/proc/cpuinfo
这几个文件获取总的Cpu时间、进程的Cpu时间、线程的Cpu时间、Cpu的个数的信息,然后通过一定的算法进行计算(采样两个足够短的时间间隔的Cpu快照与进程快照来计算进程的Cpu使用率)。
-
总的Cpu使用率计算计算方法:
-
1、采样两个足够短的时间间隔的Cpu快照,分别记作t1,t2,其中t1、t2的结构均为:(user、nice、system、idle、iowait、irq、softirq)的7元组;
-
2、计算总的Cpu时间片totalCpuTime
-
a) 把第一次的所有cpu使用情况求和,得到s1;
-
b) 把第二次的所有cpu使用情况求和,得到s2;
-
c) s2 - s1得到这个时间间隔内的所有时间片,即totalCpuTime = s2 - s1 ;
-
-
-
3、计算空闲时间idle
- idle = 第二次的第四列 - 第一次的第四列
-
4、计算cpu使用率
- pcpu=100* (total-idle)/total
-
某一进程Cpu使用率的计算计算方法:
-
1.采样两个足够短的时间间隔的cpu快照与进程快照,
-
a) 每一个cpu快照均为(user、nice、system、idle、iowait、irq、softirq)的7元组;
-
b) 每一个进程快照均为 (utime、stime、cutime、cstime)的4元组;
-
-
2. 分别根据 a和b的方式计算出两个时刻的总的cpu时间与进程的cpu时间,分别记作:totalCpuTime1、totalCpuTime2、processCpuTime1、processCpuTime2
-
3. 计算该进程的cpu使用率pcpu = 100*( processCpuTime2– processCpuTime1)/ (totalCpuTime2– totalCpuTime1) (按100%计算,如果是多核情况下还需乘以cpu的个数);
class PerfSense:
def __init__(self, deviceTup=('', '')):
self.deviceID, self.phone_name = deviceTup
self.prefix_id = '-s %s' % self.deviceID if self.deviceID else ''
self.package = ''
self.pid = self.get_pid()
self.colorCode = 36
# 获取进程pid
def get_pid(self):
if not self.package:
self.package = getFocusedPackage()
pidInfo = getAdbResponse('adb %s shell ps "|" grep %s' % (self.prefix_id, self.package))
# pidInfo = getAdbResponse('adb %s shell ps "|" grep %s' % (self.prefix_id, self.package))
pid = pidInfo.split()[1]
return pid
def getTotalCpuTime(self):
totalCpuInfo = getAdbResponse("adb %s shell cat /proc/stat" % self.prefix_id)
totalCpuTimeList = re.findall('cpu\s(.*?)\\r', totalCpuInfo)[0].split()[:7]
totalCpuTime = reduce(lambda x, y: int(x) + int(y), totalCpuTimeList)
return totalCpuTime
def getProcessCpuTime(self):
processCpuInfo = getAdbResponse("adb %s shell cat /proc/%s/stat" % (self.prefix_id, self.pid))
processCpuTimeList = processCpuInfo.split()[13:17]
processCpuTime = reduce(lambda x, y: int(x) + int(y), processCpuTimeList)
return processCpuTime
def getSingCpuRate(self):
processCpuTime_1 = self.getProcessCpuTime()
totalCpuTime_1 = self.getTotalCpuTime()
time.sleep(0.5)
processCpuTime_2 = self.getProcessCpuTime()
totalCpuTime_2 = self.getTotalCpuTime()
cpuRate = int((processCpuTime_2 - processCpuTime_1) / (totalCpuTime_2 - totalCpuTime_1) * 100)
return cpuRate
def getCpuRate(self):
print("\033[1;36m**********************************")
print("Start to get CPU Utilization Rate:")
print("**********************************\033[1;33m")
count = readConfig.MemorySetting.count
cpuRateList = []
try:
with tqdm(range(count), ascii=True) as t:
for _ in t:
cpuRateList.append(self.getSingCpuRate())
except KeyboardInterrupt as e: # 捕获意外终止程序的异常,例如Ctrl + C
print(e)
# print(cpuRateList)
value = sorted(cpuRateList)[1:-1]
mem_ave, mem_min, mem_max = np.average(value), np.min(value), np.max(value)
print("\033[1;%sm内存平均值:%s\t内存最小值:%s\t内存最大值:%s" %
(str(self.colorCode), mem_ave, mem_min, mem_max))
self.colorCode -= 2
cpuRateDict = {'mem_ave': mem_ave, 'mem_min': mem_min, 'mem_max': mem_max}
return {self.phone_name: cpuRateDict}