Tue, 06 Jan 2015 21:39:09 +0100
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"; |