Instaneous CPU usage in linux

There are two approaches of getting cpu usage in linux in general, top and ps. Top is nice in that it gives cpu% over an interval, ps is nice in that it’s lightweight and plays well with scripts without needing to parse the output overly much, it’s less nice in that the only option is to get cumulative cpu usage over the lifetime of the process.

Here’s a third option. It uses perl and actually looks at the number of “jiffies” used by the process and the number of “jiffies” used by the system. It gives a value which really does make sense, though it might be weird to interpret. If you have a 3 cpu system, it will report up to about 33% for a process running on a single processor. If you wanted to know relative what top reports, just multiply through by 3. There are sometimes some slight counting errors, i.e. over a short interval you might get 35% on a 3 cpu system for a single core process, which is clearly impossible, but the correlation is very good, and such small errors do not decrease its utility to me. This started as a babysitter for deluge, so the variable names still reflect that. There’s an extra +1 in the denominator to prevent a divide by zero error for very short intervals.

Almost forgot usage, ./cpu_usage processName intervalInSeconds iterations
defaults to ./cpu_usage processName 3 1

use strict;
use Time::HiRes qw(usleep nanosleep);

my $process_name = "$ARGV[0]";
my $deluge_id = `ps -ww -C $process_name -o pid --no-header|perl -pe 's/ //g'`;
my $totalcmd = "head -n 1 /proc/stat|awk '{print \$2+\$3+\$4+\$5+\$6+\$7+\$8}'";
my $delugecmd = "awk '{print \$14+\$15}' /proc/$deluge_id/stat";
my $deluge_jiffies = `$delugecmd`;
my $total_jiffies = `$totalcmd`;
my $deluge_jiffies_old = 0;
my $total_jiffies_old = 0;
my $pcpu = 0;
my $sleeptime = 1000000*3;#second number is seconds
if($#ARGV+1 > 1){$sleeptime = 1000000*$ARGV[1];}
my $maxiter = 1;
if($#ARGV+1 > 2){$maxiter = $ARGV[2];}
my $curriter = 0;
while ( $maxiter < 0 || $curriter < $maxiter)
$deluge_jiffies_old = $deluge_jiffies;
$total_jiffies_old = $total_jiffies;
$deluge_id = `ps -ww -C $process_name -o pid --no-header|perl -pe 's/ //g'`;
$deluge_jiffies = `$delugecmd`;
$total_jiffies = `$totalcmd`;
$pcpu = 100*($deluge_jiffies - $deluge_jiffies_old)/($total_jiffies - $total_jiffies_old + 1);
#print "\%cpu = $pcpu\n";
print "$pcpu\n";

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: