#!/usr/bin/perl # # loadmem - print memory load averages (scan rate). Solaris 8+. # # This Perl program uses the Sun::Solaris::Kstat library to fetch values. # # 21-Aug-2004, ver 0.80 (check for new versions, http://www.brendangregg.com) # # # USAGE: loadmem [-h] | [interval [count]] # loadmem # print a 1 second sample # loadmem -h # print help # loadmem 1 # print continually, every 1 second # loadmem 1 5 # print 5 times, every 1 second # # The load averages are based on dividing the scan rate for all the CPUs # by the speed of slow scan, averaged across the interval. A load average # of 1.00 would indicate that on average the kernel was scanning through # memory at a slow pace looking for pages of memory to pageout. A memory # shortage. A load average of 6.00 would indicate rapid scanning through # memory indicating a greater demand for memory. # # A load of 0.00 indicates no current memory shortage reported (yet you # may only have 1% memory left - there just isn't any current demand). # # That this program requires Solaris 8 or newer needs to be kept in mind, # as this means the filesystem cache is managed by the cyclic page cache; # in previous versions of Solaris a consistant level of scanning was # normal as this was maintenance for the filesystem cache. Now with # the cyclic page cache any consistant scanning at all indicates a # memory shortage. # # The scan rate values are divided by slowscan (usually 100) to keep the # values at levels similar to the other load programs. # # # SEE ALSO: kstat -m cpu_stat [interval [count]] # vmstat # # 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] # # 22-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", "Mem Time","1sec","5sec","15sec","1min","5min","15min"); } # # Store old and get new values # unshift(@Scan,$scan); unshift(@Update,$update); ($scan,$update) = fetch(); # # Calculate load averages # $sec1 = ratio($scan,$Scan[0],$update,$Update[0]); $sec5 = ratio($scan,$Scan[4],$update,$Update[4]); $sec15 = ratio($scan,$Scan[14],$update,$Update[14]); $min1 = ratio($scan,$Scan[59],$update,$Update[59]); $min5 = ratio($scan,$Scan[299],$update,$Update[299]); $min15 = ratio($scan,$Scan[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(@Scan) if $count > 901; pop(@Update) if $count > 901; } # # --- Subroutines --- # # fetch - fetch KStat values for the scanrate. The values used are # scan and snaptime. # sub fetch { my ($scan,$time,$driver,$instance,$category); my (%Driver,%Instance,%Category); $scan = 0; $Kstat->update(); $Driver = $Kstat->{cpu_stat}; foreach $instance (keys(%$Driver)) { $Instance = $Driver->{$instance}; foreach $category (keys(%$Instance)) { $Category = $Instance->{$category}; if (defined $$Category{scan}) { $scan += $$Category{scan}; # use the last wlastupdate value found, $time = $$Category{snaptime}; } } } # # Divide scanrate by slowscan. This gives more sensible load averages, # eg a consistant load of 1.00 indicates consistantly at slowscan. # slowscan is usually 100. # $scan = $scan / $Kstat->{unix}->{0}->{system_pages}->{slowscan}; return ($scan,$time); } # 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 <