CPU使用率の算出方法


Windowsでは、タスクマネージャを使用してシステムのさまざまなリソースの使用状況を表示することができます.私たちが常に関心を持っているのはCPUの使用率です.Linuxでは、このような可視化されたソフトウェアがありますが、変化し続ける数字がどのように計算されているのか気になるかもしれません.
次に、psutilがCPUの使用率をどのように計算しているかを分析します.
psutilについて簡単に紹介します.pythonは現在のシステムリソースを取得するサードパーティモジュールで、プラットフォームにまたがってシステムの各方面のリソースを取得することができます.
psutilシステムのcpu使用率を取得する方法はcpu_percent()は、intervalとpercpuの2つのパラメータがあり、intervalはcpuの使用率を計算する時間間隔を指定し、percpuは総使用率を選択するか、各cpuの使用率を選択するかを指定します.
システムcpuの使用状況を説明するには、主にいくつかの点があります.
userシステムが起動してから現在まで、CPUはユーザ状態の運転時間にある.nice値が負のプロセスは含まれません.
niceシステムの起動から現在まで、CPU niceが負の値のプロセスに占めるcpu時間
システムの起動から現在までCPUがカーネル状態の運転時間
idleシステムの起動から現在まで、CPUはiowait以外の待ち時間
iowaitシステム起動から現在まで、CPU io待ち時間
IRqシステムの起動から現在までのCPUのハード割り込みにかかる時間
softirqシステムの起動から現在まで、CPUソフトの割り込みにかかる時間
Stepシステムの起動から現在まで、CPUが他の仮想環境のオペレーティングシステムを実行するのにかかる時間
guestシステムの起動から現在まで、Linuxカーネルによって制御されたクライアントオペレーティングシステム上の仮想cpuをCPUが実行する時間
guest_niceはシステム起動から現在まで、Linuxカーネルで制御されたクライアントオペレーティングシステム上の仮想cpuをCPUが実行する時間であり、niceは負のプロセスである
以上のパラメータの意味を知ると、ある期間のcpu使用率を計算するのは難しくないが、cpuリソースは高速で変化しているため、cpu使用率を計算するのは一定期間しかなく、2つの時点をt 1とt 2に設定し、
CPUのt 1およびt 2時間の合計使用時間:(user 2+nice 2+system 2+idle 2+iowait 2+irq 2+softirq 2+steal 2+guest 2+guest_nice 2)-(user 1+nice 1+system 1+idle 1+iowait 1+irq 1+softirq 1+steal 1+guest 1+guest_nice 1)
CPUの空き時間:(idle 2-idle 1)
CPUのt 1およびt 2時間の使用率=CPU非アイドル時間/CPU総時間*100%=(1-CPUのアイドル時間/CPU総時間)*100%
次のようになります.
CPU(t 1,t 2)使用率:1-(idle 2-idle 1)/(user 2+nice 2+system 2+idle 2+iowait 2+irq 2+softirq 2+steal 2+guest 2+guest_nice 2)-(user 1+nice 1+system 1+idle 1+iowait 1+irq 1+softirq 1+steal 1+guest 1+guest_nice 1))
使用率の計算方法を簡単に理解しましたが、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