Accurate calculation of CPU usage given in percentage in Linux? Accurate calculation of CPU usage given in percentage in Linux? linux linux

Accurate calculation of CPU usage given in percentage in Linux?


According the htop source code, my assumptions looks like they are valid:

(see static inline double LinuxProcessList_scanCPUTime(LinuxProcessList* this) function at LinuxProcessList.c)

// Guest time is already accounted in usertimeusertime = usertime - guest;                             # As you see here, it subtracts guest from user timenicetime = nicetime - guestnice;                         # and guest_nice from nice time// Fields existing on kernels >= 2.6// (and RHEL's patched kernel 2.4...)unsigned long long int idlealltime = idletime + ioWait;  # ioWait is added in the idleTimeunsigned long long int systemalltime = systemtime + irq + softIrq;unsigned long long int virtalltime = guest + guestnice;unsigned long long int totaltime = usertime + nicetime + systemalltime + idlealltime + steal + virtalltime;

And so, from fields listed in the first line of /proc/stat: (see section 1.8 at documentation)

     user    nice   system  idle      iowait irq   softirq  steal  guest  guest_nicecpu  74608   2520   24433   1117073   6176   4054  0        0      0      0

Algorithmically, we can calculate the CPU usage percentage like:

PrevIdle = previdle + previowaitIdle = idle + iowaitPrevNonIdle = prevuser + prevnice + prevsystem + previrq + prevsoftirq + prevstealNonIdle = user + nice + system + irq + softirq + stealPrevTotal = PrevIdle + PrevNonIdleTotal = Idle + NonIdle# differentiate: actual value minus the previous onetotald = Total - PrevTotalidled = Idle - PrevIdleCPU_Percentage = (totald - idled)/totald


The following is a bash script which is based on Vangelis's answer. It produces output like this:

total 49.1803cpu0 14.2857cpu1 100cpu2 28.5714cpu3 100cpu4 30cpu5 25

Create a file called get_cpu_usage.sh

Run it using the following command: bash get_cpu_usage.sh 0.2

The argument is the number of seconds to measure. In this case it's 200 milliseconds.

The contents are:

#!/bin/shsleepDurationSeconds=$1previousDate=$(date +%s%N | cut -b1-13)previousStats=$(cat /proc/stat)sleep $sleepDurationSecondscurrentDate=$(date +%s%N | cut -b1-13)currentStats=$(cat /proc/stat)    cpus=$(echo "$currentStats" | grep -P 'cpu' | awk -F " " '{print $1}')for cpu in $cpusdo    currentLine=$(echo "$currentStats" | grep "$cpu ")    user=$(echo "$currentLine" | awk -F " " '{print $2}')    nice=$(echo "$currentLine" | awk -F " " '{print $3}')    system=$(echo "$currentLine" | awk -F " " '{print $4}')    idle=$(echo "$currentLine" | awk -F " " '{print $5}')    iowait=$(echo "$currentLine" | awk -F " " '{print $6}')    irq=$(echo "$currentLine" | awk -F " " '{print $7}')    softirq=$(echo "$currentLine" | awk -F " " '{print $8}')    steal=$(echo "$currentLine" | awk -F " " '{print $9}')    guest=$(echo "$currentLine" | awk -F " " '{print $10}')    guest_nice=$(echo "$currentLine" | awk -F " " '{print $11}')    previousLine=$(echo "$previousStats" | grep "$cpu ")    prevuser=$(echo "$previousLine" | awk -F " " '{print $2}')    prevnice=$(echo "$previousLine" | awk -F " " '{print $3}')    prevsystem=$(echo "$previousLine" | awk -F " " '{print $4}')    previdle=$(echo "$previousLine" | awk -F " " '{print $5}')    previowait=$(echo "$previousLine" | awk -F " " '{print $6}')    previrq=$(echo "$previousLine" | awk -F " " '{print $7}')    prevsoftirq=$(echo "$previousLine" | awk -F " " '{print $8}')    prevsteal=$(echo "$previousLine" | awk -F " " '{print $9}')    prevguest=$(echo "$previousLine" | awk -F " " '{print $10}')    prevguest_nice=$(echo "$previousLine" | awk -F " " '{print $11}')        PrevIdle=$((previdle + previowait))    Idle=$((idle + iowait))    PrevNonIdle=$((prevuser + prevnice + prevsystem + previrq + prevsoftirq + prevsteal))    NonIdle=$((user + nice + system + irq + softirq + steal))    PrevTotal=$((PrevIdle + PrevNonIdle))    Total=$((Idle + NonIdle))    totald=$((Total - PrevTotal))    idled=$((Idle - PrevIdle))    CPU_Percentage=$(awk "BEGIN {print ($totald - $idled)/$totald*100}")    if [[ "$cpu" == "cpu" ]]; then        echo "total "$CPU_Percentage    else        echo $cpu" "$CPU_Percentage    fidone


Hey i was also researching for the topic and found this thread really helpful. I used Vangelis Tasoulas formula to write a small python script for this. Attached is my Python code for the issue. It loads the cpu usage per cpu_id every second. Maybe its helps others as well. Also comments/suggestions are welcome :-)

#!/usr/bin/python # -*- coding: utf-8 -*-'''Created on 04.12.2014@author: plagtag'''from time import sleepimport sysclass GetCpuLoad(object):    '''    classdocs    '''    def __init__(self, percentage=True, sleeptime = 1):        '''        @parent class: GetCpuLoad        @date: 04.12.2014        @author: plagtag        @info:         @param:        @return: CPU load in percentage        '''        self.percentage = percentage        self.cpustat = '/proc/stat'        self.sep = ' '         self.sleeptime = sleeptime    def getcputime(self):        '''        http://stackoverflow.com/questions/23367857/accurate-calculation-of-cpu-usage-given-in-percentage-in-linux        read in cpu information from file        The meanings of the columns are as follows, from left to right:            0cpuid: number of cpu            1user: normal processes executing in user mode            2nice: niced processes executing in user mode            3system: processes executing in kernel mode            4idle: twiddling thumbs            5iowait: waiting for I/O to complete            6irq: servicing interrupts            7softirq: servicing softirqs        #the formulas from htop              user    nice   system  idle      iowait irq   softirq  steal  guest  guest_nice        cpu  74608   2520   24433   1117073   6176   4054  0        0      0      0        Idle=idle+iowait        NonIdle=user+nice+system+irq+softirq+steal        Total=Idle+NonIdle # first line of file for all cpus        CPU_Percentage=((Total-PrevTotal)-(Idle-PrevIdle))/(Total-PrevTotal)        '''        cpu_infos = {} #collect here the information        with open(self.cpustat,'r') as f_stat:            lines = [line.split(self.sep) for content in f_stat.readlines() for line in content.split('\n') if line.startswith('cpu')]            #compute for every cpu            for cpu_line in lines:                if '' in cpu_line: cpu_line.remove('')#remove empty elements                cpu_line = [cpu_line[0]]+[float(i) for i in cpu_line[1:]]#type casting                cpu_id,user,nice,system,idle,iowait,irq,softrig,steal,guest,guest_nice = cpu_line                Idle=idle+iowait                NonIdle=user+nice+system+irq+softrig+steal                Total=Idle+NonIdle                #update dictionionary                cpu_infos.update({cpu_id:{'total':Total,'idle':Idle}})            return cpu_infos    def getcpuload(self):        '''        CPU_Percentage=((Total-PrevTotal)-(Idle-PrevIdle))/(Total-PrevTotal)        '''        start = self.getcputime()        #wait a second        sleep(self.sleeptime)        stop = self.getcputime()        cpu_load = {}        for cpu in start:            Total = stop[cpu]['total']            PrevTotal = start[cpu]['total']            Idle = stop[cpu]['idle']            PrevIdle = start[cpu]['idle']            CPU_Percentage=((Total-PrevTotal)-(Idle-PrevIdle))/(Total-PrevTotal)*100            cpu_load.update({cpu: CPU_Percentage})        return cpu_loadif __name__=='__main__':    x = GetCpuLoad()    while True:        try:            data = x.getcpuload()            print data        except KeyboardInterrupt:            sys.exit("Finished")