Android CPU占用率计算方式(对齐Perf Dog)

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}
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值