tools/rb/bloatdiff.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 # This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 # License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
michael@0 5
michael@0 6
michael@0 7 ################################################################################
michael@0 8
michael@0 9 sub usage() {
michael@0 10 print <<EOUSAGE;
michael@0 11 # bloatdiff.pl - munges the output from
michael@0 12 # XPCOM_MEM_BLOAT_LOG=1
michael@0 13 # firefox-bin -P default resource:///res/bloatcycle.html
michael@0 14 # so that it does some summary and stats stuff.
michael@0 15 #
michael@0 16 # To show leak test results for a set of changes, do something like this:
michael@0 17 #
michael@0 18 # XPCOM_MEM_BLOAT_LOG=1
michael@0 19 # firefox-bin -P default resource:///res/bloatcycle.html > a.out
michael@0 20 # **make change**
michael@0 21 # firefox-bin -P default resource:///res/bloatcycle.html > b.out
michael@0 22 # bloatdiff.pl a.out b.out
michael@0 23
michael@0 24 EOUSAGE
michael@0 25 }
michael@0 26
michael@0 27 $OLDFILE = $ARGV[0];
michael@0 28 $NEWFILE = $ARGV[1];
michael@0 29 #$LABEL = $ARGV[2];
michael@0 30
michael@0 31 if (!$OLDFILE or
michael@0 32 ! -e $OLDFILE or
michael@0 33 -z $OLDFILE) {
michael@0 34 print "\nError: Previous log file not specified, does not exist, or is empty.\n\n";
michael@0 35 &usage();
michael@0 36 exit 1;
michael@0 37 }
michael@0 38
michael@0 39 if (!$NEWFILE or
michael@0 40 ! -e $NEWFILE or
michael@0 41 -z $NEWFILE) {
michael@0 42 print "\nError: Current log file not specified, does not exist, or is empty.\n\n";
michael@0 43 &usage();
michael@0 44 exit 1;
michael@0 45 }
michael@0 46
michael@0 47 sub processFile {
michael@0 48 my ($filename, $map, $prevMap) = @_;
michael@0 49 open(FH, $filename);
michael@0 50 while (<FH>) {
michael@0 51 if (m{
michael@0 52 ^\s*(\d+)\s # Line number
michael@0 53 ([\w:]+)\s+ # Name
michael@0 54 (-?\d+)\s+ # Size
michael@0 55 (-?\d+)\s+ # Leaked
michael@0 56 (-?\d+)\s+ # Objects Total
michael@0 57 (-?\d+)\s+ # Objects Rem
michael@0 58 \(\s*(-?[\d.]+)\s+ # Objects Mean
michael@0 59 \+/-\s+
michael@0 60 ([\w.]+)\)\s+ # Objects StdDev
michael@0 61 (-?\d+)\s+ # Reference Total
michael@0 62 (-?\d+)\s+ # Reference Rem
michael@0 63 \(\s*(-?[\d.]+)\s+ # Reference Mean
michael@0 64 \+/-\s+
michael@0 65 ([\w\.]+)\) # Reference StdDev
michael@0 66 }x) {
michael@0 67 $$map{$2} = { name => $2,
michael@0 68 size => $3,
michael@0 69 leaked => $4,
michael@0 70 objTotal => $5,
michael@0 71 objRem => $6,
michael@0 72 objMean => $7,
michael@0 73 objStdDev => $8,
michael@0 74 refTotal => $9,
michael@0 75 refRem => $10,
michael@0 76 refMean => $11,
michael@0 77 refStdDev => $12,
michael@0 78 bloat => $3 * $5 # size * objTotal
michael@0 79 };
michael@0 80 } else {
michael@0 81 # print "failed to parse: $_\n";
michael@0 82 }
michael@0 83 }
michael@0 84 close(FH);
michael@0 85 }
michael@0 86
michael@0 87 %oldMap = ();
michael@0 88 processFile($OLDFILE, \%oldMap);
michael@0 89
michael@0 90 %newMap = ();
michael@0 91 processFile($NEWFILE, \%newMap);
michael@0 92
michael@0 93 ################################################################################
michael@0 94
michael@0 95 $inf = 9999999.99;
michael@0 96
michael@0 97 sub getLeaksDelta {
michael@0 98 my ($key) = @_;
michael@0 99 my $oldLeaks = $oldMap{$key}{leaked} || 0;
michael@0 100 my $newLeaks = $newMap{$key}{leaked};
michael@0 101 my $percentLeaks = 0;
michael@0 102 if ($oldLeaks == 0) {
michael@0 103 if ($newLeaks != 0) {
michael@0 104 # there weren't any leaks before, but now there are!
michael@0 105 $percentLeaks = $inf;
michael@0 106 }
michael@0 107 }
michael@0 108 else {
michael@0 109 $percentLeaks = ($newLeaks - $oldLeaks) / $oldLeaks * 100;
michael@0 110 }
michael@0 111 # else we had no record of this class before
michael@0 112 return ($newLeaks - $oldLeaks, $percentLeaks);
michael@0 113 }
michael@0 114
michael@0 115 ################################################################################
michael@0 116
michael@0 117 sub getBloatDelta {
michael@0 118 my ($key) = @_;
michael@0 119 my $newBloat = $newMap{$key}{bloat};
michael@0 120 my $percentBloat = 0;
michael@0 121 my $oldSize = $oldMap{$key}{size} || 0;
michael@0 122 my $oldTotal = $oldMap{$key}{objTotal} || 0;
michael@0 123 my $oldBloat = $oldTotal * $oldSize;
michael@0 124 if ($oldBloat == 0) {
michael@0 125 if ($newBloat != 0) {
michael@0 126 # this class wasn't used before, but now it is
michael@0 127 $percentBloat = $inf;
michael@0 128 }
michael@0 129 }
michael@0 130 else {
michael@0 131 $percentBloat = ($newBloat - $oldBloat) / $oldBloat * 100;
michael@0 132 }
michael@0 133 # else we had no record of this class before
michael@0 134 return ($newBloat - $oldBloat, $percentBloat);
michael@0 135 }
michael@0 136
michael@0 137 ################################################################################
michael@0 138
michael@0 139 foreach $key (keys %newMap) {
michael@0 140 my ($newLeaks, $percentLeaks) = getLeaksDelta($key);
michael@0 141 my ($newBloat, $percentBloat) = getBloatDelta($key);
michael@0 142 $newMap{$key}{leakDelta} = $newLeaks;
michael@0 143 $newMap{$key}{leakPercent} = $percentLeaks;
michael@0 144 $newMap{$key}{bloatDelta} = $newBloat;
michael@0 145 $newMap{$key}{bloatPercent} = $percentBloat;
michael@0 146 }
michael@0 147
michael@0 148 ################################################################################
michael@0 149
michael@0 150 # Print a value of bytes out in a reasonable
michael@0 151 # KB, MB, or GB form. Copied from build-seamonkey-util.pl, sorry. -mcafee
michael@0 152 sub PrintSize($) {
michael@0 153
michael@0 154 # print a number with 3 significant figures
michael@0 155 sub PrintNum($) {
michael@0 156 my ($num) = @_;
michael@0 157 my $rv;
michael@0 158 if ($num < 1) {
michael@0 159 $rv = sprintf "%.3f", ($num);
michael@0 160 } elsif ($num < 10) {
michael@0 161 $rv = sprintf "%.2f", ($num);
michael@0 162 } elsif ($num < 100) {
michael@0 163 $rv = sprintf "%.1f", ($num);
michael@0 164 } else {
michael@0 165 $rv = sprintf "%d", ($num);
michael@0 166 }
michael@0 167 }
michael@0 168
michael@0 169 my ($size) = @_;
michael@0 170 my $rv;
michael@0 171 if ($size > 1000000000) {
michael@0 172 $rv = PrintNum($size / 1000000000.0) . "G";
michael@0 173 } elsif ($size > 1000000) {
michael@0 174 $rv = PrintNum($size / 1000000.0) . "M";
michael@0 175 } elsif ($size > 1000) {
michael@0 176 $rv = PrintNum($size / 1000.0) . "K";
michael@0 177 } else {
michael@0 178 $rv = PrintNum($size);
michael@0 179 }
michael@0 180 }
michael@0 181
michael@0 182
michael@0 183 print "Bloat/Leak Delta Report\n";
michael@0 184 print "--------------------------------------------------------------------------------------\n";
michael@0 185 print "Current file: $NEWFILE\n";
michael@0 186 print "Previous file: $OLDFILE\n";
michael@0 187 print "----------------------------------------------leaks------leaks%------bloat------bloat%\n";
michael@0 188
michael@0 189 if (! $newMap{"TOTAL"} or
michael@0 190 ! $newMap{"TOTAL"}{bloat}) {
michael@0 191 # It's OK if leaked or leakPercent are 0 (in fact, that would be good).
michael@0 192 # If bloatPercent is zero, it is also OK, because we may have just had
michael@0 193 # two runs exactly the same or with no new bloat.
michael@0 194 print "\nError: unable to calculate bloat/leak data.\n";
michael@0 195 print "There is no data present.\n\n";
michael@0 196 print "HINT - Did your test run complete successfully?\n";
michael@0 197 print "HINT - Are you pointing at the right log files?\n\n";
michael@0 198 &usage();
michael@0 199 exit 1;
michael@0 200 }
michael@0 201
michael@0 202 printf "%-40s %10s %10.2f%% %10s %10.2f%%\n",
michael@0 203 ("TOTAL",
michael@0 204 $newMap{"TOTAL"}{leaked}, $newMap{"TOTAL"}{leakPercent},
michael@0 205 $newMap{"TOTAL"}{bloat}, $newMap{"TOTAL"}{bloatPercent});
michael@0 206
michael@0 207 ################################################################################
michael@0 208
michael@0 209 sub percentStr {
michael@0 210 my ($p) = @_;
michael@0 211 if ($p == $inf) {
michael@0 212 return "-";
michael@0 213 }
michael@0 214 else {
michael@0 215 return sprintf "%10.2f%%", $p;
michael@0 216 }
michael@0 217 }
michael@0 218
michael@0 219 # NEW LEAKS
michael@0 220 @keys = sort { $newMap{$b}{leakPercent} <=> $newMap{$a}{leakPercent} } keys %newMap;
michael@0 221 my $needsHeading = 1;
michael@0 222 my $total = 0;
michael@0 223 foreach $key (@keys) {
michael@0 224 my $percentLeaks = $newMap{$key}{leakPercent};
michael@0 225 my $leaks = $newMap{$key}{leaked};
michael@0 226 if ($percentLeaks > 0 && $key !~ /TOTAL/) {
michael@0 227 if ($needsHeading) {
michael@0 228 printf "--NEW-LEAKS-----------------------------------leaks------leaks%%-----------------------\n";
michael@0 229 $needsHeading = 0;
michael@0 230 }
michael@0 231 printf "%-40s %10s %10s\n", ($key, $leaks, percentStr($percentLeaks));
michael@0 232 $total += $leaks;
michael@0 233 }
michael@0 234 }
michael@0 235 if (!$needsHeading) {
michael@0 236 printf "%-40s %10s\n", ("TOTAL", $total);
michael@0 237 }
michael@0 238
michael@0 239 # FIXED LEAKS
michael@0 240 @keys = sort { $newMap{$b}{leakPercent} <=> $newMap{$a}{leakPercent} } keys %newMap;
michael@0 241 $needsHeading = 1;
michael@0 242 $total = 0;
michael@0 243 foreach $key (@keys) {
michael@0 244 my $percentLeaks = $newMap{$key}{leakPercent};
michael@0 245 my $leaks = $newMap{$key}{leaked};
michael@0 246 if ($percentLeaks < 0 && $key !~ /TOTAL/) {
michael@0 247 if ($needsHeading) {
michael@0 248 printf "--FIXED-LEAKS---------------------------------leaks------leaks%%-----------------------\n";
michael@0 249 $needsHeading = 0;
michael@0 250 }
michael@0 251 printf "%-40s %10s %10s\n", ($key, $leaks, percentStr($percentLeaks));
michael@0 252 $total += $leaks;
michael@0 253 }
michael@0 254 }
michael@0 255 if (!$needsHeading) {
michael@0 256 printf "%-40s %10s\n", ("TOTAL", $total);
michael@0 257 }
michael@0 258
michael@0 259 # NEW BLOAT
michael@0 260 @keys = sort { $newMap{$b}{bloatPercent} <=> $newMap{$a}{bloatPercent} } keys %newMap;
michael@0 261 $needsHeading = 1;
michael@0 262 $total = 0;
michael@0 263 foreach $key (@keys) {
michael@0 264 my $percentBloat = $newMap{$key}{bloatPercent};
michael@0 265 my $bloat = $newMap{$key}{bloat};
michael@0 266 if ($percentBloat > 0 && $key !~ /TOTAL/) {
michael@0 267 if ($needsHeading) {
michael@0 268 printf "--NEW-BLOAT-----------------------------------bloat------bloat%%-----------------------\n";
michael@0 269 $needsHeading = 0;
michael@0 270 }
michael@0 271 printf "%-40s %10s %10s\n", ($key, $bloat, percentStr($percentBloat));
michael@0 272 $total += $bloat;
michael@0 273 }
michael@0 274 }
michael@0 275 if (!$needsHeading) {
michael@0 276 printf "%-40s %10s\n", ("TOTAL", $total);
michael@0 277 }
michael@0 278
michael@0 279 # ALL LEAKS
michael@0 280 @keys = sort { $newMap{$b}{leaked} <=> $newMap{$a}{leaked} } keys %newMap;
michael@0 281 $needsHeading = 1;
michael@0 282 $total = 0;
michael@0 283 foreach $key (@keys) {
michael@0 284 my $leaks = $newMap{$key}{leaked};
michael@0 285 my $percentLeaks = $newMap{$key}{leakPercent};
michael@0 286 if ($leaks > 0) {
michael@0 287 if ($needsHeading) {
michael@0 288 printf "--ALL-LEAKS-----------------------------------leaks------leaks%%-----------------------\n";
michael@0 289 $needsHeading = 0;
michael@0 290 }
michael@0 291 printf "%-40s %10s %10s\n", ($key, $leaks, percentStr($percentLeaks));
michael@0 292 if ($key !~ /TOTAL/) {
michael@0 293 $total += $leaks;
michael@0 294 }
michael@0 295 }
michael@0 296 }
michael@0 297 if (!$needsHeading) {
michael@0 298 # printf "%-40s %10s\n", ("TOTAL", $total);
michael@0 299 }
michael@0 300
michael@0 301 # ALL BLOAT
michael@0 302 @keys = sort { $newMap{$b}{bloat} <=> $newMap{$a}{bloat} } keys %newMap;
michael@0 303 $needsHeading = 1;
michael@0 304 $total = 0;
michael@0 305 foreach $key (@keys) {
michael@0 306 my $bloat = $newMap{$key}{bloat};
michael@0 307 my $percentBloat = $newMap{$key}{bloatPercent};
michael@0 308 if ($bloat > 0) {
michael@0 309 if ($needsHeading) {
michael@0 310 printf "--ALL-BLOAT-----------------------------------bloat------bloat%%-----------------------\n";
michael@0 311 $needsHeading = 0;
michael@0 312 }
michael@0 313 printf "%-40s %10s %10s\n", ($key, $bloat, percentStr($percentBloat));
michael@0 314 if ($key !~ /TOTAL/) {
michael@0 315 $total += $bloat;
michael@0 316 }
michael@0 317 }
michael@0 318 }
michael@0 319 if (!$needsHeading) {
michael@0 320 # printf "%-40s %10s\n", ("TOTAL", $total);
michael@0 321 }
michael@0 322
michael@0 323 # NEW CLASSES
michael@0 324 @keys = sort { $newMap{$b}{bloatDelta} <=> $newMap{$a}{bloatDelta} } keys %newMap;
michael@0 325 $needsHeading = 1;
michael@0 326 my $ltotal = 0;
michael@0 327 my $btotal = 0;
michael@0 328 foreach $key (@keys) {
michael@0 329 my $leaks = $newMap{$key}{leaked};
michael@0 330 my $bloat = $newMap{$key}{bloat};
michael@0 331 my $percentBloat = $newMap{$key}{bloatPercent};
michael@0 332 if ($percentBloat == $inf && $key !~ /TOTAL/) {
michael@0 333 if ($needsHeading) {
michael@0 334 printf "--CLASSES-NOT-REPORTED-LAST-TIME--------------leaks------bloat------------------------\n";
michael@0 335 $needsHeading = 0;
michael@0 336 }
michael@0 337 printf "%-40s %10s %10s\n", ($key, $leaks, $bloat);
michael@0 338 if ($key !~ /TOTAL/) {
michael@0 339 $ltotal += $leaks;
michael@0 340 $btotal += $bloat;
michael@0 341 }
michael@0 342 }
michael@0 343 }
michael@0 344 if (!$needsHeading) {
michael@0 345 printf "%-40s %10s %10s\n", ("TOTAL", $ltotal, $btotal);
michael@0 346 }
michael@0 347
michael@0 348 # OLD CLASSES
michael@0 349 @keys = sort { ($oldMap{$b}{bloat} || 0) <=> ($oldMap{$a}{bloat} || 0) } keys %oldMap;
michael@0 350 $needsHeading = 1;
michael@0 351 $ltotal = 0;
michael@0 352 $btotal = 0;
michael@0 353 foreach $key (@keys) {
michael@0 354 if (!defined($newMap{$key})) {
michael@0 355 my $leaks = $oldMap{$key}{leaked};
michael@0 356 my $bloat = $oldMap{$key}{bloat};
michael@0 357 if ($needsHeading) {
michael@0 358 printf "--CLASSES-THAT-WENT-AWAY----------------------leaks------bloat------------------------\n";
michael@0 359 $needsHeading = 0;
michael@0 360 }
michael@0 361 printf "%-40s %10s %10s\n", ($key, $leaks, $bloat);
michael@0 362 if ($key !~ /TOTAL/) {
michael@0 363 $ltotal += $leaks;
michael@0 364 $btotal += $bloat;
michael@0 365 }
michael@0 366 }
michael@0 367 }
michael@0 368 if (!$needsHeading) {
michael@0 369 printf "%-40s %10s %10s\n", ("TOTAL", $ltotal, $btotal);
michael@0 370 }
michael@0 371
michael@0 372 print "--------------------------------------------------------------------------------------\n";

mercurial