#!/usr/bin/env perl
use strict;

# Parses a file generated by:
#   cd /proc; grep '' [0-9]*/maps
# Skips anything that isn't an imap process.

my $curpid = 0;
my $isimap = 0;
my $count = 0;
my (%cur, %total);

while (<>) {
  chop;
  if (/^(\d+)\/maps:([^-]+)-([^ ]+) ([^ ]+) ([^ ]+) ([^ ]+) ([^ ]+) +(.*)$/) {
    my ($pid, $start, $end, $perm, $name) = ($1, $2, $3, $4, $8);
    my $size = eval("0x$end") - eval("0x$start");
    
    if ($pid ne $curpid) {
      if ($curpid != 0 && $isimap) {
	$count++;
	foreach my $key (keys %cur) {
	  if (!defined($total{$key})) {
	    $total{$key} = $cur{$key};
	  } else {
	    $total{$key} += $cur{$key};
	  }
	}
      }
      $curpid = $pid;
      $isimap = 0;
      %cur = ();
    }
    if ($name =~ /\/imap$/) {
      $isimap = 1;
    }
    if ($perm !~ /w/) {
      next;
    }
    $name = "[anonymous]" if ($name eq "");
    if (!defined($cur{$name})) {
      $cur{$name} = $size;
    } else {
      $cur{$name} += $size;
    }
  } else {
    die "Invalid input: $_";
  }
}

my $total_mem = 0;
my $key_count = 0;
printf("Total(MB) Avg(kB) Name\n");
foreach my $key (sort keys %total) {
  my $t = $total{$key};
  printf("%9u %7u %s\n", $t/1024/1024, $t/$count/1024, $key);
  $total_mem += $t;
  $key_count++;
}
printf("%9u %7u TOTAL\n", $total_mem/1024/1024, $total_mem/$key_count/1024);
