Allow diffbloatdump to read its own input back in (so that we can run fix-*-stack over its output (which is much faster than running it over a whole log) and still diff that output against different output. Not part of the build.
authordbaron@dbaron.org
Mon, 05 May 2008 21:47:23 -0700
changeset 14968 10c551c0f0febd20755495bd3f597f5e6e8ed5ec
parent 14967 cb80fe955989b6e5fb4ee643d7beac7f2e5dffb9
child 14969 2e8366fd932d9fe74b0c0878c67fd06fc5588712
push id25
push userjorendorff@mozilla.com
push dateFri, 09 May 2008 18:10:52 +0000
treeherdermozilla-central@b7dd3823dbdd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone1.9pre
Allow diffbloatdump to read its own input back in (so that we can run fix-*-stack over its output (which is much faster than running it over a whole log) and still diff that output against different output. Not part of the build.
tools/trace-malloc/diffbloatdump.pl
--- a/tools/trace-malloc/diffbloatdump.pl
+++ b/tools/trace-malloc/diffbloatdump.pl
@@ -49,36 +49,81 @@ use strict;
 use Getopt::Long;
 
 $::opt_help = 0;
 $::opt_depth = 6;
 $::opt_include_zero = 0;
 $::opt_allocation_count = 0;
 $::opt_use_address = 0;
 
+# XXX Change --use-address to be the default and remove the option
+# once tinderbox is no longer using it without --use-address.
+
 Getopt::Long::Configure("pass_through");
 Getopt::Long::GetOptions("help", "allocation-count", "depth=i",
                          "include-zero", "use-address");
 
 if ($::opt_help) {
     die "usage: diffbloatdump.pl [options] <dump1> <dump2>
   --help                 Display this message
 
   --allocation-count     Use allocation count rather than size (i.e., treat
                            all sizes as 1).
   --depth=<num>          Only display <num> frames at top of allocation stack.
   --include-zero         Display subtrees totalling zero.
   --use-address          Don't ignore the address part of the stack trace
                            (can make comparison more accurate when comparing
                            results from the same build)
+
+  The input files (<dump1> and <dump2> above) are either trace-malloc
+  memory dumps OR this script's output.  (If this script's output,
+  --allocation-count and --use-address are ignored.)  If the input files
+  have .gz or .bz2 extension, they are uncompressed.
 ";
 }
 
 my $calltree = { count => 0 }; # leave children undefined
 
+sub get_child($$) {
+    my ($node, $frame) = @_;
+    if (!defined($node->{children})) {
+        $node->{children} = {};
+    }
+    if (!defined($node->{children}->{$frame})) {
+        $node->{children}->{$frame} = { count => 0 };
+    }
+    return $node->{children}->{$frame};
+}
+
+sub add_tree_file($$$) {
+    my ($infile, $firstline, $factor) = @_;
+
+    my @nodestack;
+    $nodestack[1] = $calltree;
+    $firstline =~ /^(-?\d+) malloc$/;
+    $calltree->{count} += $1 * $factor;
+
+    my $lineno = 1;
+    while (!eof($infile)) {
+        my $line = <$infile>;
+        ++$lineno;
+        $line =~ /^( *)(-?\d+) (.*)$/ || die "malformed input, line $lineno";
+        my $depth = length($1);
+        my $count = $2;
+        my $frame = $3;
+        die "malformed input, line $lineno" if ($depth % 2 != 0);
+        $depth /= 2;
+        die "malformed input, line $lineno" if ($depth > $#nodestack);
+        $#nodestack = $depth;
+        my $node = get_child($nodestack[$depth], $frame);
+        push @nodestack, $node;
+        $node->{count} += $count * $factor;
+    }
+}
+
 sub add_file($$) {
     # Takes (1) a reference to a file descriptor for input and (2) the
     # factor to multiply the stacks by (generally +1 or -1).
     # Returns a reference to an array representing the stack, allocation
     # site in array[0].
     sub read_stack($) {
         my ($infile) = @_;
         my $line;
@@ -108,42 +153,46 @@ sub add_file($$) {
     sub add_stack($$) {
         my @stack = @{$_[0]};
         my $factor = $_[1];
 
         my $i = 0;
         my $node = $calltree;
         while ($i < $#stack && $i < $::opt_depth) {
             $node->{count} += $factor;
-            if (!defined($node->{children})) {
-                $node->{children} = {};
-            }
-            if (!defined($node->{children}->{$stack[$i]})) {
-                $node->{children}->{$stack[$i]} = { count => 0 };
-            }
-            $node = $node->{children}->{$stack[$i]};
+            $node = get_child($node, $stack[$i]);
             ++$i;
         }
         $node->{count} += $factor;
     }
 
     my ($infile, $factor) = @_;
 
     if ($infile =~ /\.bz2$/) {
         # XXX This doesn't propagate errors from bzip2.
         open (INFILE, "bzip2 -cd '$infile' |") || die "Can't open input \"$infile\"";
     } elsif ($infile =~ /\.gz$/) {
         # XXX This doesn't propagate errors from gzip.
         open (INFILE, "gzip -cd '$infile' |") || die "Can't open input \"$infile\"";
     } else {
         open (INFILE, "<$infile") || die "Can't open input \"$infile\"";
     }
+    my $first = 1;
     while ( ! eof(INFILE) ) {
         # read the type and address
         my $line = <INFILE>;
+        if ($first) {
+            $first = 0;
+            if ($line =~ /^-?\d+ malloc$/) {
+                # We're capable of reading in our own output as well.
+                add_tree_file(\*INFILE, $line, $factor);
+                close INFILE;
+                return;
+            }
+        }
         unless ($line =~ /.*\((\d*)\)[\r|\n]/) {
             die "badly formed allocation header in $infile";
         }
         my $size;
         if ($::opt_allocation_count) {
             $size = 1;
         } else {
             $size = $1;