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
How to calculate the CPU usage of a process by PID in Linux from C?
You need to parse out the data from /proc/<PID>/stat
. These are the first few fields (from Documentation/filesystems/proc.txt
in your kernel source):
Table 1-3: Contents of the stat files (as of 2.6.22-rc3)
..............................................................................
Field Content
pid process id
tcomm filename of the executable
state state (R is running, S is sleeping, D is sleeping in an
uninterruptible wait, Z is zombie, T is traced or stopped)
ppid process id of the parent process
pgrp pgrp of the process
sid session id
tty_nr tty the process uses
tty_pgrp pgrp of the tty
flags task flags
min_flt number of minor faults
cmin_flt number of minor faults with child's
maj_flt number of major faults
cmaj_flt number of major faults with child's
utime user mode jiffies
stime kernel mode jiffies
cutime user mode jiffies with child's
cstime kernel mode jiffies with child's
You're probably after utime
and/or stime
. You'll also need to read the cpu
line from /proc/stat
, which looks like:
cpu 192369 7119 480152 122044337 14142 9937 26747 0 0
This tells you the cumulative CPU time that's been used in various categories, in units of jiffies. You need to take the sum of the values on this line to get a time_total
measure.
Read both utime
and stime
for the process you're interested in, and read time_total
from /proc/stat
. Then sleep for a second or so, and read them all again. You can now calculate the CPU usage of the process over the sampling time, with:
user_util = 100 * (utime_after - utime_before) / (time_total_after - time_total_before);
sys_util = 100 * (stime_after - stime_before) / (time_total_after - time_total_before);
Make sense?
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;
}
}
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
C Program to get CPU usage for a PID and all its children
Yes, the parent needs to wait for the CPU time of the children to be added in (see manual entry for getrusage
link). Also see this answer for more details.
Calculating CPU Usage of a Process in Android
Explanation of error
I suspect that you used the value in /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq
as your hertz
value. This is incorrect since that file gives you the CPU hardware clock frequency, but you must use the Linux kernel clock frequency as your hertz
value.
The CPU hardware clock and Linux kernel clock are different. The Linux kernel -- which Android runs -- has its own timer (clock) which it updates at a certain frequency; the frequency at which this timer updates is the kernel hertz (HZ
) value.
For historical reasons, the clock tick values listed in Linux proc and sys files are scaled from the kernel HZ
frequency to a common frequency via the Linux kernel USER_HZ
constant. It is this USER_HZ
constant which we must use as the hertz
value in our calculations.
Acquisition of data
- uptime:
226.06
seconds - utime:
38
clock ticks - stime:
32
clock ticks - starttime:
13137
clock ticks - Hertz:
100
(Linux kernelUSER_HZ
constant)- This is under the assumption of an unmodified Android system.
Computation
total_time = utime + stime = 38 + 32 = 70
seconds = uptime - (starttime / Hertz) = 226.06 - (13137 / 100) = 94.69
cpu_usage = 100 * ((total_time / Hertz) / seconds) = 100 * ((70 / 100) / 94.69) = 0.7392...
Solution
The total CPU usage of your process is about 0.739%. If this seems small, remember that your process shares the CPU with all the other processes on the system: the majority of normal processes are idle for most of their life, so any one process will typically average a low total CPU usage.
Calculate CPU per process
Under a normal invocation of top
(no arguments), the %CPU
column is the proportion of ticks used by the process against the total ticks provided by one CPU, over a period of time.
From the top.c source, the %CPU
field is calculated as:
float u = (float)p->pcpu * Frame_tscale;
where pcpu for a process is the elapsed user time + system time since the last display:
hist_new[Frame_maxtask].tics = tics = (this->utime + this->stime);
...
if(ptr) tics -= ptr->tics;
...
// we're just saving elapsed tics, to be converted into %cpu if
// this task wins it's displayable screen row lottery... */
this->pcpu = tics;
and:
et = (timev.tv_sec - oldtimev.tv_sec)
+ (float)(timev.tv_usec - oldtimev.tv_usec) / 1000000.0;
Frame_tscale = 100.0f / ((float)Hertz * (float)et * (Rc.mode_irixps ? 1 : Cpu_tot));
Hertz
is 100 ticks/second on most systems (grep 'define HZ' /usr/include/asm*/param.h
), et
is the elapsed time in seconds since the last displayed frame, and Cpu_tot
is the numer of CPUs (but the 1 is what's used by default).
So, the equation on a system using 100 ticks per second for a process over T seconds is:
(curr_utime + curr_stime - (last_utime + last_stime)) / (100 * T) * 100
The script becomes:
#!/bin/bash
PID=$1
SLEEP_TIME=3 # seconds
HZ=100 # ticks/second
prev_ticks=0
while true; do
sfile=$(cat /proc/$PID/stat)
utime=$(awk '{print $14}' <<< "$sfile")
stime=$(awk '{print $15}' <<< "$sfile")
ticks=$(($utime + $stime))
pcpu=$(bc <<< "scale=4 ; ($ticks - $prev_ticks) / ($HZ * $SLEEP_TIME) * 100")
prev_ticks="$ticks"
echo $pcpu
sleep $SLEEP_TIME
done
The key differences between this approach and that of your original script is that top is computing its CPU time percentages against 1 CPU, whereas you were attempting to do so against the aggregate total for all CPUs. It's also true that you can compute the exact aggregate ticks over a period of time by doing Hertz * time * n_cpus
, and that it may not necessarily be the case that the numbers in /proc/stat will sum correctly:
$ grep 'define HZ' /usr/include/asm*/param.h
/usr/include/asm-generic/param.h:#define HZ 100
$ grep ^processor /proc/cpuinfo | wc -l
16
$ t1=$(awk '/^cpu /{sum=$2+$3+$4+$5+$6+$7+$8+$9+$10; print sum}' /proc/stat) ; sleep 1 ; t2=$(awk '/^cpu /{sum=$2+$3+$4+$5+$6+$7+$8+$9+$10; print sum}' /proc/stat) ; echo $(($t2 - $t1))
1602
Related Topics
Mount Smb/Cifs Share Within a Docker Container
How to Write a Bash Script to Restart a Process If It Dies
How to Generate a Core Dump in Linux on a Segmentation Fault
What Is Better "Int 0X80" or "Syscall" in 32-Bit Code on Linux
How to Show All Shared Libraries Used by Executables in Linux
How to Programmatically Create a New Cron Job
Using the "Alternate Screen" in a Bash Script
Bash Alias Command With Both Single and Double Quotes
How to Preserve Line Breaks When Storing Command Output to a Variable
Why Are the Backslash and Semicolon Required With the Find Command'S -Exec Option
Exit Code of Variable Assignment to Command Substitution in Bash
&&' Vs. '&' With the 'Test' Command in Bash
Linux Flock, How to "Just" Lock a File
Run an Ansible Task Only When the Variable Contains a Specific String