tools/trace-malloc/diffbloatdump.pl

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rwxr-xr-x

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 #!/usr/bin/perl -w
michael@0 2 # vim:cindent:ts=8:et:sw=4:
michael@0 3 # This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 # License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
michael@0 6
michael@0 7 # This script produces a diff between two files that are the result of
michael@0 8 # calling NS_TraceMallocDumpAllocations. Such files can be created
michael@0 9 # through the command-line option --shutdown-leaks=<filename> or through
michael@0 10 # the DOM function window.TraceMallocDumpAllocations(<filename>). Both
michael@0 11 # methods will work only if --trace-malloc=<malloc-log> is also given on
michael@0 12 # the command line.
michael@0 13
michael@0 14 use 5.004;
michael@0 15 use strict;
michael@0 16 use Getopt::Long;
michael@0 17
michael@0 18 $::opt_help = 0;
michael@0 19 $::opt_depth = 6;
michael@0 20 $::opt_include_zero = 0;
michael@0 21 $::opt_allocation_count = 0;
michael@0 22 $::opt_use_address = 0;
michael@0 23
michael@0 24 # XXX Change --use-address to be the default and remove the option
michael@0 25 # once tinderbox is no longer using it without --use-address.
michael@0 26
michael@0 27 Getopt::Long::Configure("pass_through");
michael@0 28 Getopt::Long::GetOptions("help", "allocation-count", "depth=i",
michael@0 29 "include-zero", "use-address");
michael@0 30
michael@0 31 if ($::opt_help) {
michael@0 32 die "usage: diffbloatdump.pl [options] <dump1> <dump2>
michael@0 33 --help Display this message
michael@0 34
michael@0 35 --allocation-count Use allocation count rather than size (i.e., treat
michael@0 36 all sizes as 1).
michael@0 37 --depth=<num> Only display <num> frames at top of allocation stack.
michael@0 38 --include-zero Display subtrees totalling zero.
michael@0 39 --use-address Don't ignore the address part of the stack trace
michael@0 40 (can make comparison more accurate when comparing
michael@0 41 results from the same build)
michael@0 42
michael@0 43 The input files (<dump1> and <dump2> above) are either trace-malloc
michael@0 44 memory dumps OR this script's output. (If this script's output,
michael@0 45 --allocation-count and --use-address are ignored.) If the input files
michael@0 46 have .gz or .bz2 extension, they are uncompressed.
michael@0 47 ";
michael@0 48 }
michael@0 49
michael@0 50 my $calltree = { count => 0 }; # leave children undefined
michael@0 51
michael@0 52 sub get_child($$) {
michael@0 53 my ($node, $frame) = @_;
michael@0 54 if (!defined($node->{children})) {
michael@0 55 $node->{children} = {};
michael@0 56 }
michael@0 57 if (!defined($node->{children}->{$frame})) {
michael@0 58 $node->{children}->{$frame} = { count => 0 };
michael@0 59 }
michael@0 60 return $node->{children}->{$frame};
michael@0 61 }
michael@0 62
michael@0 63 sub add_tree_file($$$) {
michael@0 64 my ($infile, $firstline, $factor) = @_;
michael@0 65
michael@0 66 my @nodestack;
michael@0 67 $nodestack[1] = $calltree;
michael@0 68 $firstline =~ /^(-?\d+) malloc$/;
michael@0 69 $calltree->{count} += $1 * $factor;
michael@0 70
michael@0 71 my $lineno = 1;
michael@0 72 while (!eof($infile)) {
michael@0 73 my $line = <$infile>;
michael@0 74 ++$lineno;
michael@0 75 $line =~ /^( *)(-?\d+) (.*)$/ || die "malformed input, line $lineno";
michael@0 76 my $depth = length($1);
michael@0 77 my $count = $2;
michael@0 78 my $frame = $3;
michael@0 79 die "malformed input, line $lineno" if ($depth % 2 != 0);
michael@0 80 $depth /= 2;
michael@0 81 die "malformed input, line $lineno" if ($depth > $#nodestack);
michael@0 82 $#nodestack = $depth;
michael@0 83 my $node = get_child($nodestack[$depth], $frame);
michael@0 84 push @nodestack, $node;
michael@0 85 $node->{count} += $count * $factor;
michael@0 86 }
michael@0 87 }
michael@0 88
michael@0 89 sub add_file($$) {
michael@0 90 # Takes (1) a reference to a file descriptor for input and (2) the
michael@0 91 # factor to multiply the stacks by (generally +1 or -1).
michael@0 92 # Returns a reference to an array representing the stack, allocation
michael@0 93 # site in array[0].
michael@0 94 sub read_stack($) {
michael@0 95 my ($infile) = @_;
michael@0 96 my $line;
michael@0 97 my @stack;
michael@0 98
michael@0 99 # read the data at the memory location
michael@0 100 while ( defined($infile) && ($line = <$infile>) && substr($line,0,1) eq "\t" ) {
michael@0 101 # do nothing
michael@0 102 }
michael@0 103
michael@0 104 # read the stack
michael@0 105 do {
michael@0 106 chomp($line);
michael@0 107 if ( ! $::opt_use_address &&
michael@0 108 $line =~ /(.*)\[(.*)\]/) {
michael@0 109 $line = $1;
michael@0 110 }
michael@0 111 $stack[$#stack+1] = $line;
michael@0 112 } while ( defined($infile) && ($line = <$infile>) && $line ne "\n" && $line ne "\r\n" );
michael@0 113
michael@0 114 return \@stack;
michael@0 115 }
michael@0 116
michael@0 117 # adds the stack given as a parameter (reference to array, $stack[0] is
michael@0 118 # allocator) to $calltree, with the call count multiplied by $factor
michael@0 119 # (typically +1 or -1).
michael@0 120 sub add_stack($$) {
michael@0 121 my @stack = @{$_[0]};
michael@0 122 my $factor = $_[1];
michael@0 123
michael@0 124 my $i = 0;
michael@0 125 my $node = $calltree;
michael@0 126 while ($i < $#stack && $i < $::opt_depth) {
michael@0 127 $node->{count} += $factor;
michael@0 128 $node = get_child($node, $stack[$i]);
michael@0 129 ++$i;
michael@0 130 }
michael@0 131 $node->{count} += $factor;
michael@0 132 }
michael@0 133
michael@0 134 my ($infile, $factor) = @_;
michael@0 135
michael@0 136 if ($infile =~ /\.bz2$/) {
michael@0 137 # XXX This doesn't propagate errors from bzip2.
michael@0 138 open (INFILE, "bzip2 -cd '$infile' |") || die "Can't open input \"$infile\"";
michael@0 139 } elsif ($infile =~ /\.gz$/) {
michael@0 140 # XXX This doesn't propagate errors from gzip.
michael@0 141 open (INFILE, "gzip -cd '$infile' |") || die "Can't open input \"$infile\"";
michael@0 142 } else {
michael@0 143 open (INFILE, "<$infile") || die "Can't open input \"$infile\"";
michael@0 144 }
michael@0 145 my $first = 1;
michael@0 146 while ( ! eof(INFILE) ) {
michael@0 147 # read the type and address
michael@0 148 my $line = <INFILE>;
michael@0 149 if ($first) {
michael@0 150 $first = 0;
michael@0 151 if ($line =~ /^-?\d+ malloc$/) {
michael@0 152 # We're capable of reading in our own output as well.
michael@0 153 add_tree_file(\*INFILE, $line, $factor);
michael@0 154 close INFILE;
michael@0 155 return;
michael@0 156 }
michael@0 157 }
michael@0 158 unless ($line =~ /.*\((\d*)\)[\r|\n]/) {
michael@0 159 die "badly formed allocation header in $infile";
michael@0 160 }
michael@0 161 my $size;
michael@0 162 if ($::opt_allocation_count) {
michael@0 163 $size = 1;
michael@0 164 } else {
michael@0 165 $size = $1;
michael@0 166 }
michael@0 167
michael@0 168 add_stack(read_stack(\*INFILE), $size * $factor);
michael@0 169 }
michael@0 170 close INFILE;
michael@0 171 }
michael@0 172
michael@0 173 sub print_node_indent($$$);
michael@0 174
michael@0 175 sub print_calltree() {
michael@0 176 sub print_indent($) {
michael@0 177 my ($i) = @_;
michael@0 178 while (--$i >= 0) {
michael@0 179 print " ";
michael@0 180 }
michael@0 181 }
michael@0 182
michael@0 183 sub print_node_indent($$$) {
michael@0 184 my ($nodename, $node, $indent) = @_;
michael@0 185
michael@0 186 if (!$::opt_include_zero && $node->{count} == 0) {
michael@0 187 return;
michael@0 188 }
michael@0 189
michael@0 190 print_indent($indent);
michael@0 191 print "$node->{count} $nodename\n";
michael@0 192 if (defined($node->{children})) {
michael@0 193 my %kids = %{$node->{children}};
michael@0 194 ++$indent;
michael@0 195 foreach my $kid (sort { $kids{$b}->{count} <=> $kids{$a}->{count} }
michael@0 196 keys (%kids)) {
michael@0 197 print_node_indent($kid, $kids{$kid}, $indent);
michael@0 198 }
michael@0 199 }
michael@0 200 }
michael@0 201
michael@0 202 print_node_indent("malloc", $calltree, 0);
michael@0 203 }
michael@0 204
michael@0 205 add_file($ARGV[0], -1);
michael@0 206 add_file($ARGV[1], 1);
michael@0 207 print_calltree();

mercurial