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 usertime
usertime = usertime - guest; # As you see here, it subtracts guest from user time
nicetime = 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 idleTime
unsigned 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_nice
cpu 74608 2520 24433 1117073 6176 4054 0 0 0 0
Algorithmically, we can calculate the CPU usage percentage like:
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
# differentiate: actual value minus the previous one
totald = Total - PrevTotal
idled = Idle - PrevIdle
CPU_Percentage = (totald - idled)/totald
Accurately Calculating CPU Utilization in Linux using /proc/stat
I think iowait/irq/softirq are not counted in one of the first 4 numbers. You can see the comment of irqtime_account_process_tick in kernel code for more detail:
(for Linux kernel 4.1.1)
2815 * Tick demultiplexing follows the order
2816 * - pending hardirq update <-- this is irq
2817 * - pending softirq update <-- this is softirq
2818 * - user_time
2819 * - idle_time <-- iowait is included in here, discuss below
2820 * - system time
2821 * - check for guest_time
2822 * - else account as system_time
For the idle time handling, see account_idle_time function:
2772 /*
2773 * Account for idle time.
2774 * @cputime: the cpu time spent in idle wait
2775 */
2776 void account_idle_time(cputime_t cputime)
2777 {
2778 u64 *cpustat = kcpustat_this_cpu->cpustat;
2779 struct rq *rq = this_rq();
2780
2781 if (atomic_read(&rq->nr_iowait) > 0)
2782 cpustat[CPUTIME_IOWAIT] += (__force u64) cputime;
2783 else
2784 cpustat[CPUTIME_IDLE] += (__force u64) cputime;
2785 }
If the cpu is idle AND there is some IO pending, it will count the time in CPUTIME_IOWAIT. Otherwise, it is count in CPUTIME_IDLE.
To conclude, I think the jiffies in irq/softirq should be counted as "busy" for cpu because it was actually handling some IRQ or soft IRQ. On the other hand, the jiffies in "iowait" should be counted as "idle" for cpu because it was not doing something but waiting for a pending IO to happen.
Current CPU core utilization via /proc/stat
The following program:
#include <assert.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
struct cpuusage {
char name[20];
// Absolute values since last reboot.
unsigned long long idletime;
unsigned long long workingtime;
};
struct cpustat {
char name[20];
unsigned long long user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice;
};
struct cpuusage cpuusage_from_cpustat(struct cpustat s) {
struct cpuusage r;
strncpy(r.name, s.name, sizeof(r.name));
r.name[sizeof(r.name) - 1] = '\0';
r.idletime = s.idle + s.iowait;
r.workingtime = s.user + s.nice + s.system + s.irq + s.softirq;
return r;
}
void cpuusage_show_diff(struct cpuusage now, struct cpuusage prev) {
// the number of ticks that passed by since the last measurement
const unsigned long long workingtime = now.workingtime - prev.workingtime;
const unsigned long long alltime = workingtime + (now.idletime - prev.idletime);
// they are divided by themselves - so the unit does not matter.
printf("Usage: %.0Lf%%\n", (long double)workingtime / alltime * 100.0L);
}
int main() {
struct cpuusage prev = {0};
//
const int stat = open("/proc/stat", O_RDONLY);
assert(stat != -1);
fcntl(stat, F_SETFL, O_NONBLOCK);
while (1) {
// let's read everything in one call so it's nicely synced.
int r = lseek(stat, SEEK_SET, 0);
assert(r != -1);
char buffer[10001];
const ssize_t readed = read(stat, buffer, sizeof(buffer) - 1);
assert(readed != -1);
buffer[readed] = '\0';
// Read the values from the readed buffer/
FILE *f = fmemopen(buffer, readed, "r");
// Uch, so much borign typing.
struct cpustat c = {0};
while (fscanf(f, "%19s %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu", c.name, &c.user, &c.nice,
&c.system, &c.idle, &c.iowait, &c.irq, &c.softirq, &c.steal, &c.guest,
&c.guest_nice) == 11) {
// Just an example for first cpu core.
if (strcmp(c.name, "cpu0") == 0) {
struct cpuusage now = cpuusage_from_cpustat(c);
cpuusage_show_diff(now, prev);
prev = now;
break;
}
}
fclose(f);
//
sleep(1);
}
}
Outputs the usage of the first core each second. I may be off with the calculations - consult this forum on which fields exactly to use from /dev/stat
.
Reading /proc/stat values to get cpu usage throws DivideByZeroException
This is how I solved it.
public class HardwareInfoManager : IHardwareInfoManager
{
private IConfiguration Configuration;
private List<long> oldCpuStatistics;
private List<long> newCpuStatistics;
public HardwareInfoManager(IConfiguration Configuration)
{
this.Configuration = Configuration;
oldCpuStatistics = new List<long>();
newCpuStatistics = new List<long>();
}
public HardwareInfoDto GetHardWareInfo()
{
return new HardwareInfoDto()
{
TenantId = Configuration.GetValue<string>("TenantId"),
Hostname = GetHostName(),
Temperature = GetTemperature(),
MemoryStats = GetMemoryStats(),
CPUUsage = GetCPUUsage()
};
}
private string GetHostName()
{
string hostNameFilePath = "//etc//hostname";
if (File.Exists(hostNameFilePath))
{
return (File.ReadAllText(hostNameFilePath));
}
else
{
return "";
}
}
private decimal GetTemperature()
{
string temperatureFilePath = "//sys//class//thermal//thermal_zone0//temp";
if (File.Exists(temperatureFilePath))
{
decimal output = Convert.ToDecimal(File.ReadAllText(temperatureFilePath));
output /= 1000;
//string temperature = output.ToString() + "°C";
return output;
//var file= File.ReadAllLines();
}
else
{
return 0.00M;
}
}
private MemoryStatsDto GetMemoryStats()
{
MemoryStatsDto memoryStatsDto = new MemoryStatsDto();
string memoryStatsPath = "//proc//meminfo";
if (File.Exists(memoryStatsPath))
{
var file = File.ReadAllLines(memoryStatsPath);
//Skipping all lines we are not interested in
for (int i = 0; i < 3; i++)
{
int firstOccurenceOfDigit = 0;
var memoryLine = file[i];
//index of first number , start the string until the end and store it
for (int j = 0; j < memoryLine.Length; j++)
{
if (Char.IsNumber(memoryLine[j]))
{
firstOccurenceOfDigit = j;
break;
}
}
var memoryValue = memoryLine.Substring(firstOccurenceOfDigit);
switch (i)
{
case 0:
memoryStatsDto.MemoryTotal = memoryValue;
break;
case 1:
memoryStatsDto.MemoryFree = memoryValue;
break;
case 2:
memoryStatsDto.MemoryAvailable = memoryValue;
break;
default: break;
}
}
return memoryStatsDto;
}
else
{
memoryStatsDto.MemoryAvailable = "";
memoryStatsDto.MemoryFree = "";
memoryStatsDto.MemoryTotal = "";
return memoryStatsDto;
}
}
private decimal GetCPUUsage()
{
string cpuUsagePath = "//proc//stat";
StringBuilder sb = new StringBuilder();
if (File.Exists(cpuUsagePath) && oldCpuStatistics.IsNullOrEmpty())
{
oldCpuStatistics = SaveIntsFromFilePath(cpuUsagePath, oldCpuStatistics);
Thread.Sleep(10000);
GetCPUUsage();
}
if (File.Exists(cpuUsagePath) && !oldCpuStatistics.IsNullOrEmpty())
{
newCpuStatistics = SaveIntsFromFilePath(cpuUsagePath, newCpuStatistics);
var prevIdle = oldCpuStatistics[3] + oldCpuStatistics[4];
decimal idle = newCpuStatistics[3] + newCpuStatistics[4];
var prevNonIdle = oldCpuStatistics[0] + oldCpuStatistics[1] + oldCpuStatistics[2] + oldCpuStatistics[5] + oldCpuStatistics[6] + oldCpuStatistics[7];
decimal nonIdle = newCpuStatistics[0] + newCpuStatistics[1] + newCpuStatistics[2] + newCpuStatistics[5] + newCpuStatistics[6] + newCpuStatistics[7];
var prevTotal = prevIdle + prevNonIdle;
decimal total = idle + nonIdle;
var totalDifference = total - prevTotal;
var idleDifference = idle - prevIdle;
decimal cpuPercentage = 0;
Log.Logger.Information($"TotalDifference is {totalDifference}");
Log.Logger.Information($"IdleDifference is {idleDifference}");
cpuPercentage = (totalDifference - idleDifference) * 100M / (totalDifference);
cpuPercentage = Math.Round(cpuPercentage, 2);
return cpuPercentage;
}
else
{
return 0;
}
}
private List<long> SaveIntsFromFilePath(string path, List<long> longList)
{
var firstLineOfCPUFile = File.ReadAllLines(path).First();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < firstLineOfCPUFile.Length; i++)
{
//take first index of a number until it reaches a whitespace, add to an int array
if (Char.IsNumber(firstLineOfCPUFile[i]))
{
sb.Append(firstLineOfCPUFile[i]);
//start with this index until it reaches whitespace
}
if (Char.IsWhiteSpace(firstLineOfCPUFile[i]) && i > 5)
{
longList.Add(long.Parse(sb.ToString()));
sb.Clear();
//start with this index until it reaches whitespace
}
}
sb.Clear();
for (int i = 0; i < longList.Count; i++)
{
Log.Logger.Information($"LongList index {i} value is {longList[i]}");
}
return longList;
}
}
Determining CPU utilization
You need to sample the values in /proc/stat
at two times, and calculate the average utilisation over that time. (Instantaneous utilisation doesn't make a whole lot of sense - it'll always be 100% on a single core machine, since your utilsation-measuring code is running whenever it looks).
How do I get the total CPU usage of an application from /proc/pid/stat?
Preparation
To calculate CPU usage for a specific process you'll need the following:
/proc/uptime
#1
uptime of the system (seconds)
/proc/[PID]/stat
#14
utime
- CPU time spent in user code, measured in clock ticks#15
stime
- CPU time spent in kernel code, measured in clock ticks#16
cutime
- Waited-for children's CPU time spent in user code (in clock ticks)#17
cstime
- Waited-for children's CPU time spent in kernel code (in clock ticks)#22
starttime
- Time when the process started, measured in clock ticks
- Hertz (number of clock ticks per second) of your system.
- In most cases,
getconf CLK_TCK
can be used to return the number of clock ticks. - The
sysconf(_SC_CLK_TCK)
C function call may also be used to return the hertz value.
- In most cases,
Calculation
First we determine the total time spent for the process:
total_time = utime + stime
We also have to decide whether we want to include the time from children processes. If we do, then we add those values to total_time
:
total_time = total_time + cutime + cstime
Next we get the total elapsed time in seconds since the process started:
seconds = uptime - (starttime / Hertz)
Finally we calculate the CPU usage percentage:
cpu_usage = 100 * ((total_time / Hertz) / seconds)
See also
Top and ps not showing the same cpu result
How to get total cpu usage in Linux (c++)
Calculating CPU usage of a process in Linux
Related Topics
Check If Directory Mounted with Bash
Is \D Not Supported by Grep's Basic Expressions
Understanding Load Average VS. CPU Usage
How to Append the Output to a File
How to Check for Opencv on Ubuntu 9.10
Readelf VS. Objdump: Why Are Both Needed
How to Track Child Process Using Strace
Remote Linux Server to Remote Linux Server Dir Copy. How
Setting a Gdb Exit Breakpoint Not Working
Recursively Cat All the Files into Single File
What Is a Reasonable Amount of Inotify Watches with Linux
Differencebetween Ld_Library_Path and -L at Link Time
Expression After Last Specific Character
Is There a Limit on Number of Tcp/Ip Connections Between MAChines on Linux
How to Remove All White Spaces from a Given Text File
How to Read Websocket Response in Linux Shell
Is There Any Modern Review of Solutions to the 10000 Client/Sec Problem
Is Lib{Library Name}.A/.So a Naming Convention for Static Libraries in Linux