CPU使用率的计算方法详解程序员

Windows下,大家可以使用任务理器来查看系统的各种资源使用情况,我们常常比较关心的就是CPU使用率,在Linux,同样有这样可视化的软件,但是大家可能会好奇那些不断变化的数字是怎样计算出来的?

下面,我就来分析一下psutil是怎样计算CPU的使用率的。

简单介绍一下psutil,psutil是一个python获取当前系统资源的第三方模块,可以跨平台的获取系统的各方面资源。

psutil获取系统cpu使用率的方法是cpu_percent(),其有两个参数,分别是interval和percpu,interval指定的是计算cpu使用率的时间间隔,percpu则指定是选择总的使用率还是每个cpu的使用率

描述系统cpu使用情况主要有一下几点:

user          从系统启动到现在,CPU处于用户态的运行时间。不包含nice值为负的进程。

nice          从系统启动到现在,CPUnice为负值的进程占用的cpu时间

system        从系统启动到现在,CPU处于内核态的运行时间

idle          从系统启动到现在,CPU除了 iowait外的等待时间

iowait        从系统启动到现在,CPUio 等待时间

irq           从系统启动到现在,CPU硬中断花费的时间

softirq       从系统启动到现在,CPU软中断花费的时间

steal         从系统启动到现在,CPU运行其他虚拟环境中的操作系统花费的时间

guest         从系统启动到现在,CPU运行在通过Linux内核控制的客户操作系统上的虚拟cpu的时间

guest_nice    从系统启动到现在,CPU运行在通过Linux内核控制的客户操作系统上的虚拟cpu的时间, nice 为负值进程

知道了以上参数的意思,计算某段时间内的cpu使用率就不难,由于cpu资源是在高速的变化,于是计算cpu使用率只能是在一段时间内的,设置两个时间点为t1和t2,

CPU在t1和t2时间内总的使用时间:( user2+ nice2+ system2+ idle2+ iowait2+ irq2+ softirq2 + steal2 + guest2 + guest_nice2 ) – ( user1+ nice1+ system1+ idle1+ iowait1+ irq1+ softirq1 + steal1 + guest1 + guest_nice1)

CPU的空闲时间:(idle2 -idle1)

CPU在t1和t2时间内的使用率=CPU非空闲时间/CPU总时间*100%=(1-CPU的空闲时间/CPU总时间)*100%

则:

    CPU(t1,t2)使用率:1-(idle2-idle1)/(( user2+ nice2+ system2+ idle2+ iowait2+ irq2+ softirq2 + steal2 + guest2 + guest_nice2 ) – ( user1+ nice1+ system1+ idle1+ iowait1+ irq1+ softirq1 + steal1 + guest1 + guest_nice1))

简单了解了使用率的计算方法,下面我们看一下cpu_percent是怎样实现的

def cpu_percent(interval=None, percpu=False): 
    """Return a float representing the current system-wide utilization as a percentage. 
    返回一个当前系统cpu使用率的百分比结果, 
 
 
    When interval is > 0.0 compares system CPU times elapsed before 
    and after the interval (blocking). 
     
    当interval大于0.0时,返回的是在这段时间内CUP的使用率 
 
 
    When interval is 0.0 or None compares system CPU times elapsed 
    since last call or module import, returning immediately (non 
    blocking). That means the first time this is called it will 
    return a meaningless 0.0 value which you should ignore. 
    In this case is recommended for accuracy that this function be 
    called with at least 0.1 seconds between calls. 
 
 
    当interval是0.0或者是None时,系统在调用此模块后,还没来得及运行就立即返回了,返回的是没有任何意义的0,你应该忽略调这个值,为避免这种情况,为了准确,调用这个模块时间至少为0.1秒 
     
    When percpu is True returns a list of floats representing the 
    utilization as a percentage for each CPU. 
    First element of the list refers to first CPU, second element 
    to second CPU and so on. 
    The order of the list is consistent across calls. 
 
 
    当percpu的值为True时,则返回的是一个列表,里面包含每个CPU在该段时间内的CPU使用率 
     
    Examples: 
 
 
      >>> # blocking, system-wide 
      >>> psutil.cpu_percent(interval=1) 
      2.0 
      >>> 
      >>> # blocking, per-cpu 
      >>> psutil.cpu_percent(interval=1, percpu=True) 
      [2.0, 1.0] 
      >>> 
      >>> # non-blocking (percentage since last call) 
      >>> psutil.cpu_percent(interval=None) 
      2.9 
      >>> 
    """ 
    global _last_cpu_times  #全局变量,用于表示上一个时间点cpu的各项参数,用于和下一个时间点cpu各项参数进行计算 
    global _last_per_cpu_times #全局变量,用于表示上一个时间点,各个cpu在上一个时间点的各项cpu参数,作用同上 
     
     
    blocking = interval is not None and interval > 0.0 #判断interval的值,如果interval 不为空且大余0.0,则blocking值为真,否则为假 
 
 
 
 
    def calculate(t1, t2):  #计算CPU使用率 
        t1_all = sum(t1) #计算t1时间,cpu的使用时间,为各项参数的和 
        t1_busy = t1_all - t1.idle #计算cpu的非空闲时间 
 
 
        t2_all = sum(t2) #计算t1时间,cpu的使用时间,为各项参数的和 
        t2_busy = t2_all - t2.idle #计算cpu的非空闲时间 
 
 
        # this usually indicates a float precision issue 
        if t2_busy <= t1_busy:  #如果t2时刻的非空闲时间小余t1时刻的,则直接返回0.0 
            return 0.0 
 
 
        busy_delta = t2_busy - t1_busy  #计算t1-t2时间段内CPU总的非空闲时间 
        all_delta = t2_all - t1_all     #计算t1-t2时间段内CPU总的使用时间 
        busy_perc = (busy_delta / all_delta) * 100  #计算t1-t2时间段内CPU总的使用率 
        return round(busy_perc, 1) #保留一位小数后返回 
 
 
    # system-wide usage 
    if not percpu:   #如果percpu为False 
        if blocking: #interval 不为空且大余0.0 
            t1 = cpu_times() #获取t1时刻,cpu各项参数 
            time.sleep(interval) #休眠interval时间 
        else: 
            t1 = _last_cpu_times #如果不满足interval 不为空且大余0.0 
            if t1 is None:  #当interval为None 
                # Something bad happened at import time. We'll 
                # get a meaningful result on the next call. See: 
                # https://github.com/giampaolo/psutil/pull/715 
                t1 = cpu_times() 
 
 
        #当interval为None,_last_cpu_times与t1几乎是在同一时刻计算的,值几乎相同,因此将返回0.0 
        _last_cpu_times = cpu_times() 
        return calculate(t1, _last_cpu_times) 
    # per-cpu usage 
    else: 
        ret = [] 
        if blocking: 
            tot1 = cpu_times(percpu=True) 
            time.sleep(interval) 
        else: 
            tot1 = _last_per_cpu_times 
            if tot1 is None: 
                # Something bad happened at import time. We'll 
                # get a meaningful result on the next call. See: 
                # https://github.com/giampaolo/psutil/pull/715 
                tot1 = cpu_times(percpu=True) 
        _last_per_cpu_times = cpu_times(percpu=True) 
        for t1, t2 in zip(tot1, _last_per_cpu_times): 
            ret.append(calculate(t1, t2)) #循环计算各个CPU的使用率 
        return ret 
 
 
 
 
# Use separate global vars for cpu_times_percent() so that it's 
# independent from cpu_percent() and they can both be used within 
# the same program. 
_last_cpu_times_2 = _last_cpu_times 
_last_per_cpu_times_2 = _last_per_cpu_times

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/3039.html

(0)
上一篇 2021年7月16日
下一篇 2021年7月16日

相关推荐

发表回复

登录后才能评论