#!/usr/bin/perl -w # ## Solaris memory analysis program. Shows where memory is being used. ## ## Version 1.2, 2003-Feb-21 ## Version 1.1, 2001-May-01 ## Version 1.0, 2001-Jan-01 ## ## Copyright 2003 Brandon Gillespie, Use by GPL License ## ## Brandon Gillespie, 2000/2001 ## Created ## Kurt Olsen 2001 ## Added rss calculation ## James Manning 2002 ## Added oracle shmem ## fixed byte/kbyte bug ## misc cleanup, scoping (added strict) ## Brandon Gillespie 2003 ## a lot more cleanup ## added minor shmem handling ## removed remote running # # NOTE: The numbers are not entirely accurate. This is due to various # other conditions which are too painful to follow (such as shared # memory allocation, etc). However, they do give you a general # representation of what processes and modules are using which chunks # of your memory. use strict; use Getopt::Long; use Data::Dumper; ##################################### ## parse args Getopt::Long::Configure("bundling"); my $opt_resident = 0; my $opt_cutoff = 10; my $opt_help = 0; GetOptions( "resident|r" => \$opt_resident, "cutoff|c=i" => \$opt_cutoff, "help|h" => \$opt_help, ); my $memtype = "vsz"; if ($opt_help) { print <{$owner}->{$id} = { 'key' => $key, 'attached' => $natt, 'unsub' => $natt, 'group' => $group, 'size' => $size, }; $ipcs_mem += $size; $cmds->{$cmd}++; $mem_bytes->{$cmd} += $size; $mem_totbytes += $size; } for (@psinfo) { chomp; (/^ (VSZ|RSS)/) && next; if (!/^\s*(\d+) (.*)$/) { die("Bad line: $_\n"); } my $mem = int($1) * 1024; # NOTE: ps gives it in KB, we knock down to bytes my $proc = $2; # ORACLE HACK - remove the SGA from the memory numbers if ($proc =~ /^ora/) { my %om = %{$shmem->{'oracle'}}; for my $id (sort {$om{$b}->{'size'} <=> $om{$a}->{'size'}} keys %om) { if ($om{$id}->{'unsub'} <= 0) { next; } my $orashared = $shmem->{'oracle'}->{$id}->{'size'}; if (($mem - $orashared) > 0) { $shmem->{'oracle'}->{$id}->{'unsub'}--; $mem -= $orashared; last; } } } $proc =~ s:^/bin/sh (-c )?::g; $proc =~ s/^-//; my ($cmd, @args) = split(/\s+/, $proc); my @cmd = split(/\//, $cmd); $cmd = $cmd[$#cmd]; $cmds->{$cmd}++; $mem_bytes->{$cmd} += $mem; $mem_totbytes += $mem; } my $last_mod = -1; for (@modinfo) { chomp; (/^ Id/) && next; if (!/^\s*(\d+)\s+([a-z0-9]+)\s+([a-z0-9]+)\s+([0-9-]+)\s+([0-9-]+)\s+(.*)$/) { die("Bad line: $_\n"); } if ( $1 != $last_mod ) { my $mem = hex($3); my $proc = "kmod: $6"; $cmds->{$proc}++; $mem_bytes->{$proc} += $mem; $mem_totbytes += $mem; $last_mod = $1; $mem_bytes->{"kmod (sum total)"}+= $mem; } } $cmds->{"kmod (sum total)"}=1; my $less=0; my $mem_less_tot=0; printf "%9s %4s KERNEL MODULE / PROCESS\n", "MEMORY", "#"; sub sort_bymem { return $mem_bytes->{$b} <=> $mem_bytes->{$a}; }; for my $key (sort sort_bymem keys %$mem_bytes) { my $mem_mb = $mem_bytes->{$key} / (1024.0*1024.0); if ($mem_mb < $opt_cutoff) { $mem_less_tot += $mem_mb; $less++; } else { printf "%9.2f MB %4d $key\n", $mem_mb, $cmds->{$key}; } } $mem_totbytes /= (1024.0*1024.0); if ($mem_less_tot > 0) { printf "[ %.2f MB in $less undisplayed items, each using less than $opt_cutoff MB of memory ]\n", $mem_less_tot; } if ($ipcs_mem) { printf "[ %.2f MB in shared memory (ipcs -m -b) ]\n", $ipcs_mem/1024/1024; } printf "\n%9.2f MB TOTAL\n", $mem_totbytes;