| #!/usr/bin/perl |
| |
| # ********************************************************** |
| # Copyright (c) 2005-2007 VMware, Inc. All rights reserved. |
| # ********************************************************** |
| |
| # Redistribution and use in source and binary forms, with or without |
| # modification, are permitted provided that the following conditions are met: |
| # |
| # * Redistributions of source code must retain the above copyright notice, |
| # this list of conditions and the following disclaimer. |
| # |
| # * Redistributions in binary form must reproduce the above copyright notice, |
| # this list of conditions and the following disclaimer in the documentation |
| # and/or other materials provided with the distribution. |
| # |
| # * Neither the name of VMware, Inc. nor the names of its contributors may be |
| # used to endorse or promote products derived from this software without |
| # specific prior written permission. |
| # |
| # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| # ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE |
| # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
| # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
| # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
| # DAMAGE. |
| |
| # Prints out summary of memory statistics from a global log file |
| # This script is a merger of old heapacct.pl and new memsummary.sh |
| |
| # FIXME: add cmd line arg -v |
| $verbose = 0; |
| $debug = 0; |
| |
| if ($#ARGV < 0) { |
| print "Usage: $0 <file>\n"; |
| exit 0; |
| } |
| $file = $ARGV[0]; |
| |
| open(IN, "< $file") || die "Couldn't open $file\n"; |
| while (<IN>) { |
| # heap acct: use final printed stats, since using max |
| if (/Updated-at-end Process.*heap breakdown/) { |
| while (<IN>) { |
| if (/^([^:]+): cur=.*max=\s*(\d+)K, \#=\s*(\d+)/){ |
| $hnm[$hnms++]=$1; |
| $hmax{$1}=$2; |
| $hnum{$1}=$3; |
| } else { |
| last; |
| } |
| } |
| } |
| |
| if (/^\(Begin\) All statistics/) { |
| # reset |
| $hnms = 0; |
| $pnms = 0; |
| } elsif (/Peak heap cap|Peak heap claim|Peak heap align|Peak stack|Peak mmap|Peak file|peak cap|Peak spec/) { |
| if (/^\s*(.*) \(bytes\) :\s*(\d+)/){ |
| print "Matched \"$1\" \"$2\" \"$3\"\n" if ($debug); |
| $nm=$1; |
| $val=$2; |
| $pnm[$pnms++]=$nm; |
| $p{$nm}=$val; |
| } else { |
| print "Error: $_" unless (/Peak special heap units/); |
| } |
| } elsif (/Peak total memory from OS :\s*(\d+)/){ |
| $reserved_tot=$1; |
| } elsif (/Our peak commited capacity \(bytes\) :\s*(\d+)/){ |
| $tot=$1; |
| } |
| |
| # stats we don't or haven't always had peaks for |
| if (/Heap align space \(bytes\) :\s*(\d+)/) { |
| # old logs don't have this as a peak, so take max printed |
| if ($1 > $align) { |
| $align = $1; |
| } |
| } elsif (/Heap headers \(bytes\) :\s*(\d+)/) { |
| # not a peak, so take max printed |
| if ($1 > $header) { |
| $header = $1; |
| } |
| } elsif (/Heap claimed \(bytes\) :\s*(\d+)/) { |
| # old logs don't have this as a peak, so take max printed |
| if ($1 > $claimed) { |
| $claimed = $1; |
| } |
| } |
| |
| if ($verbose) { |
| # completely separate numbers: variable-sized frequency |
| # last printed is fine since these never decrease |
| if (/Heap allocs in buckets :\s*(\d+)/) { |
| $bucket = $1; |
| } elsif (/Heap allocs variable-sized :\s*(\d+)/) { |
| $variable = $1; |
| } |
| } |
| } |
| close(IN); |
| |
| # things we don't have peak for |
| if (defined($p{'Peak heap claimed'})) { |
| $claimed = $p{'Peak heap claimed'}; |
| } |
| $tot_cap = $p{'Peak heap capacity'}; |
| $pnm[$pnms++]='Unused heap (capacity - claimed)'; |
| $p{$pnm[$pnms-1]} = $p{'Peak heap capacity'} - $claimed; |
| |
| if (!defined($p{'Peak heap align space'})) { |
| $pnm[$pnms++]='(Estimated) Peak heap align space'; |
| $p{$pnm[$pnms-1]} = $align; |
| } |
| # FIXME: don't have peak |
| $pnm[$pnms++]='(Estimated) Peak heap headers'; |
| $p{$pnm[$pnms-1]} = $header; |
| |
| |
| printf "%35s 100.00%% %10d KB\n", "TOTAL COMMITTED MEMORY", $tot/1024; |
| printf "%35s %6.2f%% %10d KB\n", "TOTAL RESERVED (non-vmm) MEMORY", |
| 100*$reserved_tot/$tot, $reserved_tot/1024; |
| for ($i=0; $i<$pnms; $i++) { |
| printf "%35s %6.2f%% %10d KB\n", $pnm[$i], |
| 100*$p{$pnm[$i]}/$tot, $p{$pnm[$i]}/1024; |
| } |
| for ($i=0; $i<$hnms; $i++) { |
| printf "%35s %6.2f%% %10d KB\n", $hnm[$i], |
| 100*1024*$hmax{$hnm[$i]}/$tot, $hmax{$hnm[$i]}; |
| $hsum += $hmax{$hnm[$i]}; |
| } |
| |
| if ($verbose) { |
| printf "Sum of heap acct is %10d KB\n", $hsum; |
| printf "Adding special %10d\n", $p{'Peak special heap capacity'}/1024; |
| printf "Adding align %10d\n", $p{'Peak heap align space'}/1024; |
| $hsum += $p{'Peak heap align space'}/1024; |
| $hsum += $p{'Peak special heap capacity'}/1024; |
| # FIXME: this often comes out negative, presumably b/c the heapacct |
| # maxes are not all simultaneous |
| printf "Rest of heap: %10d KB\n", ($p{'Peak heap capacity'}/1024) - $hsum; |
| } |
| |
| if ($verbose) { |
| # FIXME: could print out detailed bucket info w/ new stats in logfiles |
| $tot_alloc = $bucket + $variable; |
| printf "Tot alloc: %10d\n", $tot_alloc; |
| printf "Buckets: %10d => %7.3f%%\n", $bucket, 100*$bucket/$tot_alloc; |
| printf "Variable: %10d => %7.3f%%\n", $variable, 100*$variable/$tot_alloc; |
| } |