3 ################################################################################
7 # bloatdiff.pl - munges the output from
8 # XPCOM_MEM_BLOAT_LOG=1
9 # firefox-bin -P default resource:///res/bloatcycle.html
10 # so that it does some summary and stats stuff.
12 # To show leak test results for a set of changes, do something like this:
14 # XPCOM_MEM_BLOAT_LOG=1
15 # firefox-bin -P default resource:///res/bloatcycle.html > a.out
17 # firefox-bin -P default resource:///res/bloatcycle.html > b.out
18 # bloatdiff.pl a.out b.out
30 print "\nERROR - Previous log file not specified, does not exist, or is empty.\n\n";
38 print "\nERROR - Current log file not specified, does not exist, or is empty.\n\n";
44 my ($filename, $map, $prevMap) = @_;
48 ^\s
*(\d
+)\s
# Line number
52 (-?\d
+)\s
+ # Objects Total
53 (-?\d
+)\s
+ # Objects Rem
54 \
(\s
*(-?
[\d
.]+)\s
+ # Objects Mean
56 ([\w
.]+)\
)\s
+ # Objects StdDev
57 (-?\d
+)\s
+ # Reference Total
58 (-?\d
+)\s
+ # Reference Rem
59 \
(\s
*(-?
[\d
.]+)\s
+ # Reference Mean
61 ([\w\
.]+)\
) # Reference StdDev
63 $$map{$2} = { name
=> $2,
74 bloat
=> $3 * $5 # size * objTotal
77 # print "failed to parse: $_\n";
84 processFile
($OLDFILE, \
%oldMap);
87 processFile
($NEWFILE, \
%newMap);
89 ################################################################################
95 my $oldLeaks = $oldMap{$key}{leaked
} || 0;
96 my $newLeaks = $newMap{$key}{leaked
};
100 # there weren't any leaks before, but now there are!
101 $percentLeaks = $inf;
105 $percentLeaks = ($newLeaks - $oldLeaks) / $oldLeaks * 100;
107 # else we had no record of this class before
108 return ($newLeaks - $oldLeaks, $percentLeaks);
111 ################################################################################
115 my $newBloat = $newMap{$key}{bloat
};
116 my $percentBloat = 0;
117 my $oldSize = $oldMap{$key}{size
} || 0;
118 my $oldTotal = $oldMap{$key}{objTotal
} || 0;
119 my $oldBloat = $oldTotal * $oldSize;
120 if ($oldBloat == 0) {
121 if ($newBloat != 0) {
122 # this class wasn't used before, but now it is
123 $percentBloat = $inf;
127 $percentBloat = ($newBloat - $oldBloat) / $oldBloat * 100;
129 # else we had no record of this class before
130 return ($newBloat - $oldBloat, $percentBloat);
133 ################################################################################
135 foreach $key (keys %newMap) {
136 my ($newLeaks, $percentLeaks) = getLeaksDelta
($key);
137 my ($newBloat, $percentBloat) = getBloatDelta
($key);
138 $newMap{$key}{leakDelta
} = $newLeaks;
139 $newMap{$key}{leakPercent
} = $percentLeaks;
140 $newMap{$key}{bloatDelta
} = $newBloat;
141 $newMap{$key}{bloatPercent
} = $percentBloat;
144 ################################################################################
146 # Print a value of bytes out in a reasonable
147 # KB, MB, or GB form. Copied from build-seamonkey-util.pl, sorry. -mcafee
150 # print a number with 3 significant figures
155 $rv = sprintf "%.3f", ($num);
156 } elsif ($num < 10) {
157 $rv = sprintf "%.2f", ($num);
158 } elsif ($num < 100) {
159 $rv = sprintf "%.1f", ($num);
161 $rv = sprintf "%d", ($num);
167 if ($size > 1000000000) {
168 $rv = PrintNum
($size / 1000000000.0) . "G";
169 } elsif ($size > 1000000) {
170 $rv = PrintNum
($size / 1000000.0) . "M";
171 } elsif ($size > 1000) {
172 $rv = PrintNum
($size / 1000.0) . "K";
174 $rv = PrintNum
($size);
179 print "Bloat/Leak Delta Report\n";
180 print "--------------------------------------------------------------------------------------\n";
181 print "Current file: $NEWFILE\n";
182 print "Previous file: $OLDFILE\n";
183 print "----------------------------------------------leaks------leaks%------bloat------bloat%\n";
185 if (! $newMap{"TOTAL"} or
186 ! $newMap{"TOTAL"}{bloat
} or
187 ! $newMap{"TOTAL"}{bloatPercent
}) {
188 # it's OK if leaked or leakPercent are 0 (in fact, that would be good)
189 print "\nERROR - unable to calculate bloat/leak data.\n\n";
190 print "HINT - Did your test run complete successfully?\n";
191 print "HINT - Are you pointing at the right log files?\n\n";
196 printf "%-40s %10s %10.2f%% %10s %10.2f%%\n",
198 $newMap{"TOTAL"}{leaked
}, $newMap{"TOTAL"}{leakPercent
},
199 $newMap{"TOTAL"}{bloat
}, $newMap{"TOTAL"}{bloatPercent
});
201 ################################################################################
209 return sprintf "%10.2f%%", $p;
214 @keys = sort { $newMap{$b}{leakPercent
} <=> $newMap{$a}{leakPercent
} } keys %newMap;
215 my $needsHeading = 1;
217 foreach $key (@keys) {
218 my $percentLeaks = $newMap{$key}{leakPercent
};
219 my $leaks = $newMap{$key}{leaked
};
220 if ($percentLeaks > 0 && $key !~ /TOTAL/) {
222 printf "--NEW-LEAKS-----------------------------------leaks------leaks%%-----------------------\n";
225 printf "%-40s %10s %10s\n", ($key, $leaks, percentStr
($percentLeaks));
229 if (!$needsHeading) {
230 printf "%-40s %10s\n", ("TOTAL", $total);
234 @keys = sort { $newMap{$b}{leakPercent
} <=> $newMap{$a}{leakPercent
} } keys %newMap;
237 foreach $key (@keys) {
238 my $percentLeaks = $newMap{$key}{leakPercent
};
239 my $leaks = $newMap{$key}{leaked
};
240 if ($percentLeaks < 0 && $key !~ /TOTAL/) {
242 printf "--FIXED-LEAKS---------------------------------leaks------leaks%%-----------------------\n";
245 printf "%-40s %10s %10s\n", ($key, $leaks, percentStr
($percentLeaks));
249 if (!$needsHeading) {
250 printf "%-40s %10s\n", ("TOTAL", $total);
254 @keys = sort { $newMap{$b}{bloatPercent
} <=> $newMap{$a}{bloatPercent
} } keys %newMap;
257 foreach $key (@keys) {
258 my $percentBloat = $newMap{$key}{bloatPercent
};
259 my $bloat = $newMap{$key}{bloat
};
260 if ($percentBloat > 0 && $key !~ /TOTAL/) {
262 printf "--NEW-BLOAT-----------------------------------bloat------bloat%%-----------------------\n";
265 printf "%-40s %10s %10s\n", ($key, $bloat, percentStr
($percentBloat));
269 if (!$needsHeading) {
270 printf "%-40s %10s\n", ("TOTAL", $total);
274 @keys = sort { $newMap{$b}{leaked
} <=> $newMap{$a}{leaked
} } keys %newMap;
277 foreach $key (@keys) {
278 my $leaks = $newMap{$key}{leaked
};
279 my $percentLeaks = $newMap{$key}{leakPercent
};
282 printf "--ALL-LEAKS-----------------------------------leaks------leaks%%-----------------------\n";
285 printf "%-40s %10s %10s\n", ($key, $leaks, percentStr
($percentLeaks));
286 if ($key !~ /TOTAL/) {
291 if (!$needsHeading) {
292 # printf "%-40s %10s\n", ("TOTAL", $total);
296 @keys = sort { $newMap{$b}{bloat
} <=> $newMap{$a}{bloat
} } keys %newMap;
299 foreach $key (@keys) {
300 my $bloat = $newMap{$key}{bloat
};
301 my $percentBloat = $newMap{$key}{bloatPercent
};
304 printf "--ALL-BLOAT-----------------------------------bloat------bloat%%-----------------------\n";
307 printf "%-40s %10s %10s\n", ($key, $bloat, percentStr
($percentBloat));
308 if ($key !~ /TOTAL/) {
313 if (!$needsHeading) {
314 # printf "%-40s %10s\n", ("TOTAL", $total);
318 @keys = sort { $newMap{$b}{bloatDelta
} <=> $newMap{$a}{bloatDelta
} } keys %newMap;
322 foreach $key (@keys) {
323 my $leaks = $newMap{$key}{leaked
};
324 my $bloat = $newMap{$key}{bloat
};
325 my $percentBloat = $newMap{$key}{bloatPercent
};
326 if ($percentBloat == $inf && $key !~ /TOTAL/) {
328 printf "--CLASSES-NOT-REPORTED-LAST-TIME--------------leaks------bloat------------------------\n";
331 printf "%-40s %10s %10s\n", ($key, $leaks, $bloat);
332 if ($key !~ /TOTAL/) {
338 if (!$needsHeading) {
339 printf "%-40s %10s %10s\n", ("TOTAL", $ltotal, $btotal);
343 @keys = sort { ($oldMap{$b}{bloat
} || 0) <=> ($oldMap{$a}{bloat
} || 0) } keys %oldMap;
347 foreach $key (@keys) {
348 if (!defined($newMap{$key})) {
349 my $leaks = $oldMap{$key}{leaked
};
350 my $bloat = $oldMap{$key}{bloat
};
352 printf "--CLASSES-THAT-WENT-AWAY----------------------leaks------bloat------------------------\n";
355 printf "%-40s %10s %10s\n", ($key, $leaks, $bloat);
356 if ($key !~ /TOTAL/) {
362 if (!$needsHeading) {
363 printf "%-40s %10s %10s\n", ("TOTAL", $ltotal, $btotal);
366 print "--------------------------------------------------------------------------------------\n";