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")