#!/usr/bin/perl
#
# Read ltrace(1) output to calculate peak memory consumption
# Diomidis Spinellis, September 2012

use strict;
use warnings;

# Allocation overhead
my $overhead = 16;

my $current = 0;
my $allocated = 0;
my $freed = 0;
my $peak = 0;

my $nmalloc = 0;
my $nfree = 0;

# Size of allcoated memory blocks
my %size;

# Lines are of the form
# 6312 malloc(16)                                  = 0x01979da0
# 6312 free(0x0197ac50)                            = <void>
# 6312 realloc(0x12b229c60, 64)                   = 0x136447130

while (<>) {
	if (/\d+ malloc\((\d+)\)\s+\=\s*0x(\w+)/) {
		$size{$2} = $1;
		$current += $1 + $overhead;
		$allocated += $1 + $overhead;
		$nmalloc++;
		$peak = $current if ($current > $peak);
	} elsif (/\d+ free\(0x(\w+)\)/) {
		my $block_size = (defined($size{$1}) ? $size{$1} : 0) + $overhead;
		$current -= $block_size;
		$freed += $block_size;
		$nfree++;
	} elsif (/\d+ realloc\(0x(\w+), (\d+)\)\s+\=\s*0x(\w+)/) {
		my $block_size = (defined($size{$1}) ? $size{$1} : 0) + $overhead;
		$current -= $block_size;
		$freed += $block_size;
		$nfree++;
		$size{$3} = $2;
		$current += $2 + $overhead;
		$allocated += $2 + $overhead;
		$nmalloc++;
		$peak = $current if ($current > $peak);
	} else {
		print STDERR "Unmatched line: $_";
	}
}

print qq{Allocated: $allocated bytes in $nmalloc calls
Freed: $freed bytes in $nfree calls
Peak marginal memory use: $peak bytes
};
