DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Untracked file

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
use strict;
my ($freeBytes, $freeCount);
my ($usedBytes, $usedCount);
my ($uncommFreeBytes, $uncommFreeCount);
my ($freeAtEndBytes, $freeAtEndCount);
my ($overheadBytes, $overheadCount);
my ($holeBytes, $holeCount, @hole);
my ($commBytes, $uncommBytes);
# track prev address of allocation to detect holes
# Track begin and end address of contiguous block
my ($nextAddr) = 0;
my $holeTolerance = 0;

# 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;
        ($uncommFreeBytes, $uncommFreeCount) = 0;
        ($freeAtEndBytes, $freeAtEndCount) = 0;
        ($overheadBytes, $overheadCount) = 0;
        ($holeBytes, $holeCount) = 0;
        ($commBytes, $uncommBytes) = 0;
        $heading = $1;
        @hole = ();
        next;
    }
    if (/END HEAPDUMP/) {
        # Print results of heapdump
        results();
        next;
    }
    # look for blocks that are used or free
    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;

        # See if the previous heap ended with a free block
        if ($prevFree) {
            $freeAtEndBytes += $prevFree;
            $freeAtEndCount++;
        }
        $prevFree = 0;

        $commBytes += $3;
        $uncommBytes += $4;
        $overheadBytes += $2;
        $overheadCount++;
        next;
    }

    if (/ *FREE ([0-9A-Fa-f]*) : *([0-9]*) overhead *([0-9]*)/)
    {
        $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;
    }
    elsif (/ *USED ([0-9A-Fa-f]*) : *([0-9]*) overhead *([0-9]*)/)
    {
        $usedCount++;
        $usedBytes += $2;
        $overheadCount++;
        $overheadBytes += $3;
        # This wasn't a free
        $prevFree = 0;
    }
    elsif (/ *---- ([0-9A-Fa-f]*) : *([0-9]*) overhead *([0-9]*)/)
    {
        $uncommFreeCount++;
        $uncommFreeBytes += $2;
        # these won't have any overhead
        # we shouldn't view this as a free as we could shed this and
        # reduce our VmSize
        $prevFree = $2;
    }
    else {
        next;
    }
    my $addr = hex $1;
    my $size = $2;
    my $overhead = $3;

    if ($nextAddr && $addr-$nextAddr > $holeTolerance) {
        # found a hole. This is usally alignment overhead
        $holeCount ++;
        $holeBytes += $addr - $nextAddr;
    }
    $nextAddr = $addr + $size + $overhead;
}

sub results()
{
    printf "Heap statistics : $heading\n";
    printf "------------------------------------------------------------\n";
    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;
    printf "\n";
    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);
}

sub toK()
{
    my $bytes = shift;
    return $bytes / 1024;
}