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
If need to calculate how much cpu% used by a process in last 10 secs
- get total_time (13+14) in jiffies => t1 starttime(22) in jiffies => s1
--delay of 10 secs
total_time (13+14) in jiffies => t2 starttime(22) in jiffies => s2
t2-t1 *100 / s2 - s1 wouldnt give the % ??
Yes, you can say so. You can convert those values into seconds using formula:
sec = jiffies / HZ ; here - HZ = number of ticks per second
HZ value is configurable - done at kernel configuration time.
Here is my simple solution written in BASH. It is a linux/unix system monitor and process manager through procfs, like "top" or "ps". There is two versions simple monochrome(fast) and colored version(little bit slow, but useful especially for monitoring the statе of processes). I made sorting by CPU usage.
https://github.com/AraKhachatryan/top
utime, stime, cutime, cstime, starttime used for getting cpu usage and obtained from /proc/[pid]/stat file.
state, ppid, priority, nice, num_threads parameters obtained also from /proc/[pid]/stat file.
resident and data_and_stack parameters used for getting memory usage and obtained from /proc/[pid]/statm file.
function my_ps
{
pid_array=`ls /proc | grep -E '^[0-9]+$'`
clock_ticks=$(getconf CLK_TCK)
total_memory=$( grep -Po '(?<=MemTotal:\s{8})(\d+)' /proc/meminfo )
cat /dev/null > .data.ps
for pid in $pid_array
do
if [ -r /proc/$pid/stat ]
then
stat_array=( `sed -E 's/(\([^\s)]+)\s([^)]+\))/\1_\2/g' /proc/$pid/stat` )
uptime_array=( `cat /proc/uptime` )
statm_array=( `cat /proc/$pid/statm` )
comm=( `grep -Po '^[^\s\/]+' /proc/$pid/comm` )
user_id=$( grep -Po '(?<=Uid:\s)(\d+)' /proc/$pid/status )
user=$( id -nu $user_id )
uptime=${uptime_array[0]}
state=${stat_array[2]}
ppid=${stat_array[3]}
priority=${stat_array[17]}
nice=${stat_array[18]}
utime=${stat_array[13]}
stime=${stat_array[14]}
cutime=${stat_array[15]}
cstime=${stat_array[16]}
num_threads=${stat_array[19]}
starttime=${stat_array[21]}
total_time=$(( $utime + $stime ))
#add $cstime - CPU time spent in user and kernel code ( can olso add $cutime - CPU time spent in user code )
total_time=$(( $total_time + $cstime ))
seconds=$( awk 'BEGIN {print ( '$uptime' - ('$starttime' / '$clock_ticks') )}' )
cpu_usage=$( awk 'BEGIN {print ( 100 * (('$total_time' / '$clock_ticks') / '$seconds') )}' )
resident=${statm_array[1]}
data_and_stack=${statm_array[5]}
memory_usage=$( awk 'BEGIN {print( (('$resident' + '$data_and_stack' ) * 100) / '$total_memory' )}' )
printf "%-6d %-6d %-10s %-4d %-5d %-4s %-4u %-7.2f %-7.2f %-18s\n" $pid $ppid $user $priority $nice $state $num_threads $memory_usage $cpu_usage $comm >> .data.ps
fi
done
clear
printf "\e[30;107m%-6s %-6s %-10s %-4s %-3s %-6s %-4s %-7s %-7s %-18s\e[0m\n" "PID" "PPID" "USER" "PR" "NI" "STATE" "THR" "%MEM" "%CPU" "COMMAND"
sort -nr -k9 .data.ps | head -$1
read_options
}