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.

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

mercurial