#!/usr/bin/perl # memhogs: # This script loops forever, printing out: # - the date & time # - the amount of RAM being used by the top RAM-consuming processes, # - the total amount of RAM being used by all processes # - the number of pageouts (since the machine was booted) # - info on the amount of swap being used # The first command-line argument specifies the number of top RAM-consumimg # processes to be reported on. # (If no command-line argument is given, it reports the top 5 processes.) # The second command-line argument specifies the number of seconds # between iterations. # (If no 2nd command-line argument is given, it iterates every 60 seconds.) # Sample usage: memhogs 10 30 # # Cameron Hayne (macdev@hayne.net) March 2009 use strict; use warnings; sub printMemUsage($) { my ($numTop) = @_; my $psCommand = '/bin/ps axmc -o rss,comm'; my $count = 0; my $totalRssMB = 0; open(PS, "$psCommand |") or die "Failed to run '$psCommand': $!\n"; while() { if (/^\s*(\d+)\s+(.*)$/) { my $rss = $1; my $comm = $2; my $rssMB = $rss / 1024; $totalRssMB += $rssMB; if ($count++ < $numTop) { printf("%5.1f MB\t%s\n", $rssMB, $comm); } } } close(PS); printf ("total: %6.1f MB\n", $totalRssMB); } sub printDate() { my $date = localtime(time()); print "$date\n"; } sub getVmStats() { my %vmStats = (); my $vmStatsCommand = '/usr/bin/vm_stat'; open(VMSTATS, "$vmStatsCommand |") or die "Failed to run '$vmStatsCommand': $!\n"; while() { if (/^\s*([^:]+):\s*(\d+)\.$/) { my $name = $1; my $value = $2; $vmStats{$name} = $value; } } close(VMSTATS); return \%vmStats; } INIT { my $prevNumPageouts = -1; sub printNumPageouts() { my $vmStatsRef = getVmStats(); my $numPageouts = $$vmStatsRef{'Pageouts'}; if ($prevNumPageouts < 0) { print "pageouts: $numPageouts\n"; } else { my $delta = $numPageouts - $prevNumPageouts; print "pageouts: $numPageouts delta: $delta\n"; } $prevNumPageouts = $numPageouts; } } sub printSwapInfo() { system('/usr/sbin/sysctl vm.swapusage'); } sub usageError($) { my ($msg) = @_; print "Usage: $0 [numTop [loopDelay]]\n"; die "$msg\n"; } MAIN: { my $numTop = 5; # number of processes to show memory usage for my $loopDelay = 60; # number of seconds to sleep between iterations if (@ARGV) { $numTop = shift @ARGV; usageError("numTop must be positive integer") unless $numTop =~ /^\d+$/ and $numTop > 0; } if (@ARGV) { $loopDelay = shift @ARGV; usageError("loopDelay must be positive integer") unless $loopDelay =~ /^\d+$/ and $loopDelay > 0; } usageError("Too many arguments") if @ARGV; while(1) { printDate(); printMemUsage($numTop); printNumPageouts(); printSwapInfo(); print "---------------------------------------------------------\n"; sleep($loopDelay); } }