#!/usr/bin/perl # # loadcpu - print CPU load averages (threads on run queue). Solaris 8+. # # These are saturation values - not the same "load" as printed by uptime. This # Perl program uses the Sun::Solaris::Kstat library to fetch accurate values. # # 21-Aug-2004, ver 0.80 (check for new versions, http://www.brendangregg.com) # # # USAGE: loadcpu [-h] | [interval [count]] # loadcpu # print a 1 second sample # loadcpu -h # print help # loadcpu 1 # print continually, every 1 second # loadcpu 1 5 # print 5 times, every 1 second # # # The load averages are based on the length of the run queue divided by # sample time. A load average of 1.00 indicates that on average there # is a thread waiting in the ready run queue for CPU time (usually bad). # A load average of 4.00 would indicate there were four threads on average # waiting for the CPU. # # A load average of 0.00 does not mean the CPU is idle, rather that it # is not saturated. This differs to the uptime command where it is 1.00 # that indicates a CPU is not saturated (100% utilised), and where 0.00 # would mean an idle CPU. (use vmstat to determine if a CPU is idle). # # The number of CPUs should be kept in mind, but the results are not the same # as with the uptime command. A load average of 4.00 would mean that across # the CPUs there is still an average of four threads waiting for CPU time - # regardless of the CPU count this is usually undesirable. CPU count still # makes a difference, a load average of 4.00 would be dispatched sooner on # a server with many CPUs rather than say one CPU. # # KStat values used are unix:0:sysinfo:runque and unix:0:sysinfo:updates. # # # SEE ALSO: kstat -n sysinfo [interval [count]] # uptime # vmstat # # REFERENCE: "What exactly is load average?" Richard Pettit, comp.unix.solaris # # COPYRIGHT: Copyright (c) 2004 Brendan Gregg. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software Foundation, # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # (http://www.gnu.org/copyleft/gpl.html) # # Author: Brendan Gregg [Sydney, Australia] # # 21-Mar-2004 Brendan Gregg Created this. use Sun::Solaris::Kstat; my $Kstat = Sun::Solaris::Kstat->new(); # # --- Process command line args --- # if ($ARGV[0] eq "-h" || $ARGV[0] eq "--help" || $ARGV[0] eq "0") { &usage(); } $sleep = $ARGV[0]; $loop = $ARGV[1]; if ($sleep eq "") { $sleep = 1; $loop = 1; } elsif ($loop eq "") { $loop = 2**32; } $PAGESIZE = 20; # max lines per header $lines = $PAGESIZE; # counter for lines printed $| = 1; # # --- Main --- # while (1) { if ($lines++ >= $PAGESIZE) { $lines = 0; printf("%8s %6s %6s %6s %6s %6s %6s\n", "CPU Time","1sec","5sec","15sec","1min","5min","15min"); } # # Store old and get new values # unshift(@Runque,$runque); unshift(@Update,$update); ($runque,$update) = fetch(); # # Calculate load averages # $sec1 = ratio($runque,$Runque[0],$update,$Update[0]); $sec5 = ratio($runque,$Runque[4],$update,$Update[4]); $sec15 = ratio($runque,$Runque[14],$update,$Update[14]); $min1 = ratio($runque,$Runque[59],$update,$Update[59]); $min5 = ratio($runque,$Runque[299],$update,$Update[299]); $min15 = ratio($runque,$Runque[899],$update,$Update[899]); # # Print load averages # if ($sec1 ne "" && (($count % $sleep) == 0)) { @Time = localtime(); printf("%02d:%02d:%02d %6s %6s %6s %6s %6s %6s\n",$Time[2], $Time[1],$Time[0],$sec1,$sec5,$sec15,$min1,$min5,$min15); ### Check for end last if ++$printed == $loop; } $count++; ### Interval sleep (1); ### Memory cleanup pop(@Runque) if $count > 901; pop(@Update) if $count > 901; } # # --- Subroutines --- # # fetch - fetch current values for runque and updates. # sub fetch { $Kstat->update(); return ($Kstat->{unix}->{0}->{sysinfo}->{runque}, $Kstat->{unix}->{0}->{sysinfo}->{updates}); } # ratio - calculate the ratio of the count delta over time delta; # given count and oldcount, time and oldtime. Returns a string # of the value, or a null string if not enough data was given. # sub ratio { my ($count,$oldcount,$time,$oldtime) = @_; return "" unless defined $oldtime; $countd = $count - $oldcount; $timed = $time - $oldtime; if ($timed > 0) { $ratio = $countd / $timed; } else { $ratio = 0; } return sprintf("%.2f",$ratio); } # usage - print usage and exit. # sub usage { print STDERR <