2002-02-22 01:24:18 +03:00
use strict ;
my ( $ freeBytes , $ freeCount ) ;
my ( $ usedBytes , $ usedCount ) ;
2002-02-28 01:43:16 +03:00
my ( $ uncommFreeBytes , $ uncommFreeCount ) ;
2002-02-22 01:24:18 +03:00
my ( $ freeAtEndBytes , $ freeAtEndCount ) ;
my ( $ overheadBytes , $ overheadCount ) ;
my ( $ holeBytes , $ holeCount , @ hole ) ;
2002-02-28 01:43:16 +03:00
my ( $ commBytes , $ uncommBytes ) ;
2002-02-22 01:24:18 +03:00
# track prev address of allocation to detect holes
# Track begin and end address of contiguous block
2002-02-28 01:43:16 +03:00
my ( $ nextAddr ) = 0 ;
my $ holeTolerance = 0 ;
2002-02-22 01:24:18 +03:00
# Heading for heap dump
my $ heading ;
# Notes the previous block size if it was a free to track freeAtEnd.
# If prev block was not a free, this would be set to zero.
my $ prevFree = 0 ;
while ( < > )
{
if ( /BEGIN HEAPDUMP : (.*)$/ ) {
# Initialize all variables
( $ freeBytes , $ freeCount ) = 0 ;
( $ usedBytes , $ usedCount ) = 0 ;
2002-02-28 01:43:16 +03:00
( $ uncommFreeBytes , $ uncommFreeCount ) = 0 ;
2002-02-22 01:24:18 +03:00
( $ freeAtEndBytes , $ freeAtEndCount ) = 0 ;
( $ overheadBytes , $ overheadCount ) = 0 ;
( $ holeBytes , $ holeCount ) = 0 ;
2002-02-28 01:43:16 +03:00
( $ commBytes , $ uncommBytes ) = 0 ;
2002-02-22 01:24:18 +03:00
$ heading = $ 1 ;
@ hole = ( ) ;
next ;
}
if ( /END HEAPDUMP/ ) {
# Print results of heapdump
results ( ) ;
2002-02-28 01:43:16 +03:00
next ;
2002-02-22 01:24:18 +03:00
}
# look for blocks that are used or free
2002-02-28 01:43:16 +03:00
if ( /BEGIN heap/ ) {
next ;
}
if ( /END heap/ ) {
# Reset nextAddr for overhead detection
$ nextAddr = 0 ;
# See if the previous heap ended with a free block
if ( $ prevFree ) {
$ freeAtEndBytes += $ prevFree ;
$ freeAtEndCount + + ;
}
$ prevFree = 0 ;
next ;
}
if ( /REGION ([0-9A-Fa-f]*) : *overhead ([0-9]*) committed ([0-9]*) uncommitted ([0-9]*)/ ) {
# Reset nextAddr for overhead detection
$ nextAddr = 0 ;
2002-02-22 01:24:18 +03:00
# See if the previous heap ended with a free block
if ( $ prevFree ) {
$ freeAtEndBytes += $ prevFree ;
$ freeAtEndCount + + ;
}
2002-02-28 01:43:16 +03:00
$ prevFree = 0 ;
$ commBytes += $ 3 ;
$ uncommBytes += $ 4 ;
$ overheadBytes += $ 2 ;
$ overheadCount + + ;
2002-02-22 01:24:18 +03:00
next ;
}
2002-02-28 01:43:16 +03:00
if ( / *FREE ([0-9A-Fa-f]*) : *([0-9]*) overhead *([0-9]*)/ )
2002-02-22 01:24:18 +03:00
{
$ freeCount + + ;
$ freeBytes += $ 2 ;
$ overheadCount + + ;
$ overheadBytes += $ 3 ;
# This is a free. Notes it size. If the this is the end of the heap,
# this is a candidate for compaction.
$ prevFree = $ 2 ;
}
2002-02-28 01:43:16 +03:00
elsif ( / *USED ([0-9A-Fa-f]*) : *([0-9]*) overhead *([0-9]*)/ )
2002-02-22 01:24:18 +03:00
{
$ usedCount + + ;
$ usedBytes += $ 2 ;
$ overheadCount + + ;
$ overheadBytes += $ 3 ;
# This wasn't a free
$ prevFree = 0 ;
}
2002-02-28 01:43:16 +03:00
elsif ( / *---- ([0-9A-Fa-f]*) : *([0-9]*) overhead *([0-9]*)/ )
{
$ uncommFreeCount + + ;
$ uncommFreeBytes += $ 2 ;
# these wont have an overhead
# we shouldn't view this as a free as we could shed this and
# reduce our VmSize
$ prevFree = $ 2 ;
}
2002-02-22 01:24:18 +03:00
else {
next ;
}
my $ addr = hex $ 1 ;
my $ size = $ 2 ;
my $ overhead = $ 3 ;
2002-02-28 01:43:16 +03:00
if ( $ nextAddr && $ addr - $ nextAddr > $ holeTolerance ) {
# found a hole. This is usally alignment overhead
2002-02-22 01:24:18 +03:00
$ holeCount + + ;
$ holeBytes += $ addr - $ nextAddr ;
}
$ nextAddr = $ addr + $ size + $ overhead ;
}
sub results ()
{
printf "Heap statistics : $heading\n" ;
printf "------------------------------------------------------------\n" ;
2002-02-28 01:43:16 +03:00
printf "USED : %8.2f K in %6d blocks\n" , toK ( $ usedBytes ) , $ usedCount ;
printf "FREE : %8.2f K in %6d blocks\n" , toK ( $ freeBytes ) , $ freeCount ;
printf "Uncommitted FREE : %8.2f K in %6d blocks\n" , toK ( $ uncommFreeBytes ) , $ uncommFreeCount ;
printf "Overhead : %8.2f K in %6d blocks\n" , toK ( $ overheadBytes ) , $ overheadCount ;
printf "Alignment overhead : %8.2f K in %6d blocks\n" , toK ( $ holeBytes ) , $ holeCount ;
printf " Total : %8.2f K\n" , toK ( $ freeBytes + $ usedBytes + $ uncommFreeBytes + $ overheadBytes + $ holeBytes ) ;
printf "FREE at heap end : %8.2f K in %6d blocks - %5.2f%% of FREE\n" , toK ( $ freeAtEndBytes ) , $ freeAtEndCount , $ freeAtEndBytes / ( $ freeBytes + $ uncommFreeBytes ) * 100 ;
2002-02-22 01:24:18 +03:00
printf "\n" ;
2002-02-28 01:43:16 +03:00
printf "Total Commit : %8.2f K\n" , toK ( $ commBytes ) ;
printf "Total Uncommit : %8.2f K\n" , toK ( $ uncommBytes ) ;
printf " Total : %8.2f K\n" , toK ( $ uncommBytes + $ commBytes ) ;
2002-02-22 01:24:18 +03:00
}
sub toK ()
{
my $ bytes = shift ;
return $ bytes / 1024 ;
}