Bug 470455 - test_database_sync_embed_visits.js leaks, r=sdwilsh
[wine-gecko.git] / tools / rb / bloatdiff.pl
bloba4f3db40a315836011b1912db43a0ed6f4585ed1
1 #!/usr/bin/perl -w
3 ################################################################################
5 sub usage() {
6 print <<EOUSAGE;
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
16 # **make change**
17 # firefox-bin -P default resource:///res/bloatcycle.html > b.out
18 # bloatdiff.pl a.out b.out
20 EOUSAGE
23 $OLDFILE = $ARGV[0];
24 $NEWFILE = $ARGV[1];
25 #$LABEL = $ARGV[2];
27 if (!$OLDFILE or
28 ! -e $OLDFILE or
29 -z $OLDFILE) {
30 print "\nERROR - Previous log file not specified, does not exist, or is empty.\n\n";
31 &usage();
32 exit 1;
35 if (!$NEWFILE or
36 ! -e $NEWFILE or
37 -z $NEWFILE) {
38 print "\nERROR - Current log file not specified, does not exist, or is empty.\n\n";
39 &usage();
40 exit 1;
43 sub processFile {
44 my ($filename, $map, $prevMap) = @_;
45 open(FH, $filename);
46 while (<FH>) {
47 if (m{
48 ^\s*(\d+)\s # Line number
49 ([\w:]+)\s+ # Name
50 (-?\d+)\s+ # Size
51 (-?\d+)\s+ # Leaked
52 (-?\d+)\s+ # Objects Total
53 (-?\d+)\s+ # Objects Rem
54 \(\s*(-?[\d.]+)\s+ # Objects Mean
55 \+/-\s+
56 ([\w.]+)\)\s+ # Objects StdDev
57 (-?\d+)\s+ # Reference Total
58 (-?\d+)\s+ # Reference Rem
59 \(\s*(-?[\d.]+)\s+ # Reference Mean
60 \+/-\s+
61 ([\w\.]+)\) # Reference StdDev
62 }x) {
63 $$map{$2} = { name => $2,
64 size => $3,
65 leaked => $4,
66 objTotal => $5,
67 objRem => $6,
68 objMean => $7,
69 objStdDev => $8,
70 refTotal => $9,
71 refRem => $10,
72 refMean => $11,
73 refStdDev => $12,
74 bloat => $3 * $5 # size * objTotal
76 } else {
77 # print "failed to parse: $_\n";
80 close(FH);
83 %oldMap = ();
84 processFile($OLDFILE, \%oldMap);
86 %newMap = ();
87 processFile($NEWFILE, \%newMap);
89 ################################################################################
91 $inf = 9999999.99;
93 sub getLeaksDelta {
94 my ($key) = @_;
95 my $oldLeaks = $oldMap{$key}{leaked} || 0;
96 my $newLeaks = $newMap{$key}{leaked};
97 my $percentLeaks = 0;
98 if ($oldLeaks == 0) {
99 if ($newLeaks != 0) {
100 # there weren't any leaks before, but now there are!
101 $percentLeaks = $inf;
104 else {
105 $percentLeaks = ($newLeaks - $oldLeaks) / $oldLeaks * 100;
107 # else we had no record of this class before
108 return ($newLeaks - $oldLeaks, $percentLeaks);
111 ################################################################################
113 sub getBloatDelta {
114 my ($key) = @_;
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;
126 else {
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
148 sub PrintSize($) {
150 # print a number with 3 significant figures
151 sub PrintNum($) {
152 my ($num) = @_;
153 my $rv;
154 if ($num < 1) {
155 $rv = sprintf "%.3f", ($num);
156 } elsif ($num < 10) {
157 $rv = sprintf "%.2f", ($num);
158 } elsif ($num < 100) {
159 $rv = sprintf "%.1f", ($num);
160 } else {
161 $rv = sprintf "%d", ($num);
165 my ($size) = @_;
166 my $rv;
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";
173 } else {
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";
192 &usage();
193 exit 1;
196 printf "%-40s %10s %10.2f%% %10s %10.2f%%\n",
197 ("TOTAL",
198 $newMap{"TOTAL"}{leaked}, $newMap{"TOTAL"}{leakPercent},
199 $newMap{"TOTAL"}{bloat}, $newMap{"TOTAL"}{bloatPercent});
201 ################################################################################
203 sub percentStr {
204 my ($p) = @_;
205 if ($p == $inf) {
206 return "-";
208 else {
209 return sprintf "%10.2f%%", $p;
213 # NEW LEAKS
214 @keys = sort { $newMap{$b}{leakPercent} <=> $newMap{$a}{leakPercent} } keys %newMap;
215 my $needsHeading = 1;
216 my $total = 0;
217 foreach $key (@keys) {
218 my $percentLeaks = $newMap{$key}{leakPercent};
219 my $leaks = $newMap{$key}{leaked};
220 if ($percentLeaks > 0 && $key !~ /TOTAL/) {
221 if ($needsHeading) {
222 printf "--NEW-LEAKS-----------------------------------leaks------leaks%%-----------------------\n";
223 $needsHeading = 0;
225 printf "%-40s %10s %10s\n", ($key, $leaks, percentStr($percentLeaks));
226 $total += $leaks;
229 if (!$needsHeading) {
230 printf "%-40s %10s\n", ("TOTAL", $total);
233 # FIXED LEAKS
234 @keys = sort { $newMap{$b}{leakPercent} <=> $newMap{$a}{leakPercent} } keys %newMap;
235 $needsHeading = 1;
236 $total = 0;
237 foreach $key (@keys) {
238 my $percentLeaks = $newMap{$key}{leakPercent};
239 my $leaks = $newMap{$key}{leaked};
240 if ($percentLeaks < 0 && $key !~ /TOTAL/) {
241 if ($needsHeading) {
242 printf "--FIXED-LEAKS---------------------------------leaks------leaks%%-----------------------\n";
243 $needsHeading = 0;
245 printf "%-40s %10s %10s\n", ($key, $leaks, percentStr($percentLeaks));
246 $total += $leaks;
249 if (!$needsHeading) {
250 printf "%-40s %10s\n", ("TOTAL", $total);
253 # NEW BLOAT
254 @keys = sort { $newMap{$b}{bloatPercent} <=> $newMap{$a}{bloatPercent} } keys %newMap;
255 $needsHeading = 1;
256 $total = 0;
257 foreach $key (@keys) {
258 my $percentBloat = $newMap{$key}{bloatPercent};
259 my $bloat = $newMap{$key}{bloat};
260 if ($percentBloat > 0 && $key !~ /TOTAL/) {
261 if ($needsHeading) {
262 printf "--NEW-BLOAT-----------------------------------bloat------bloat%%-----------------------\n";
263 $needsHeading = 0;
265 printf "%-40s %10s %10s\n", ($key, $bloat, percentStr($percentBloat));
266 $total += $bloat;
269 if (!$needsHeading) {
270 printf "%-40s %10s\n", ("TOTAL", $total);
273 # ALL LEAKS
274 @keys = sort { $newMap{$b}{leaked} <=> $newMap{$a}{leaked} } keys %newMap;
275 $needsHeading = 1;
276 $total = 0;
277 foreach $key (@keys) {
278 my $leaks = $newMap{$key}{leaked};
279 my $percentLeaks = $newMap{$key}{leakPercent};
280 if ($leaks > 0) {
281 if ($needsHeading) {
282 printf "--ALL-LEAKS-----------------------------------leaks------leaks%%-----------------------\n";
283 $needsHeading = 0;
285 printf "%-40s %10s %10s\n", ($key, $leaks, percentStr($percentLeaks));
286 if ($key !~ /TOTAL/) {
287 $total += $leaks;
291 if (!$needsHeading) {
292 # printf "%-40s %10s\n", ("TOTAL", $total);
295 # ALL BLOAT
296 @keys = sort { $newMap{$b}{bloat} <=> $newMap{$a}{bloat} } keys %newMap;
297 $needsHeading = 1;
298 $total = 0;
299 foreach $key (@keys) {
300 my $bloat = $newMap{$key}{bloat};
301 my $percentBloat = $newMap{$key}{bloatPercent};
302 if ($bloat > 0) {
303 if ($needsHeading) {
304 printf "--ALL-BLOAT-----------------------------------bloat------bloat%%-----------------------\n";
305 $needsHeading = 0;
307 printf "%-40s %10s %10s\n", ($key, $bloat, percentStr($percentBloat));
308 if ($key !~ /TOTAL/) {
309 $total += $bloat;
313 if (!$needsHeading) {
314 # printf "%-40s %10s\n", ("TOTAL", $total);
317 # NEW CLASSES
318 @keys = sort { $newMap{$b}{bloatDelta} <=> $newMap{$a}{bloatDelta} } keys %newMap;
319 $needsHeading = 1;
320 my $ltotal = 0;
321 my $btotal = 0;
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/) {
327 if ($needsHeading) {
328 printf "--CLASSES-NOT-REPORTED-LAST-TIME--------------leaks------bloat------------------------\n";
329 $needsHeading = 0;
331 printf "%-40s %10s %10s\n", ($key, $leaks, $bloat);
332 if ($key !~ /TOTAL/) {
333 $ltotal += $leaks;
334 $btotal += $bloat;
338 if (!$needsHeading) {
339 printf "%-40s %10s %10s\n", ("TOTAL", $ltotal, $btotal);
342 # OLD CLASSES
343 @keys = sort { ($oldMap{$b}{bloat} || 0) <=> ($oldMap{$a}{bloat} || 0) } keys %oldMap;
344 $needsHeading = 1;
345 $ltotal = 0;
346 $btotal = 0;
347 foreach $key (@keys) {
348 if (!defined($newMap{$key})) {
349 my $leaks = $oldMap{$key}{leaked};
350 my $bloat = $oldMap{$key}{bloat};
351 if ($needsHeading) {
352 printf "--CLASSES-THAT-WENT-AWAY----------------------leaks------bloat------------------------\n";
353 $needsHeading = 0;
355 printf "%-40s %10s %10s\n", ($key, $leaks, $bloat);
356 if ($key !~ /TOTAL/) {
357 $ltotal += $leaks;
358 $btotal += $bloat;
362 if (!$needsHeading) {
363 printf "%-40s %10s %10s\n", ("TOTAL", $ltotal, $btotal);
366 print "--------------------------------------------------------------------------------------\n";