Bug 1886451: Add missing ifdef Nightly guards. r=dminor
[gecko.git] / tools / bloatview / bloatdiff.pl
bloba9bfa97226630ebafe59acafb92ffcd60fb183b0
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 -P default resource:///res/bloatcycle.html
14 # so that it does some summary and stats stuff.
16 # To show leak test results for a set of changes, do something like this:
18 # XPCOM_MEM_BLOAT_LOG=1
19 # firefox -P default resource:///res/bloatcycle.html > a.out
20 # **make change**
21 # firefox -P default resource:///res/bloatcycle.html > b.out
22 # bloatdiff.pl a.out b.out
24 EOUSAGE
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;
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;
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
80 } else {
81 # print "failed to parse: $_\n";
84 close(FH);
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;
108 else {
109 $percentLeaks = ($newLeaks - $oldLeaks) / $oldLeaks * 100;
111 # else we had no record of this class before
112 return ($newLeaks - $oldLeaks, $percentLeaks);
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;
130 else {
131 $percentBloat = ($newBloat - $oldBloat) / $oldBloat * 100;
133 # else we had no record of this class before
134 return ($newBloat - $oldBloat, $percentBloat);
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;
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);
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);
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;
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 "-";
214 else {
215 return sprintf "%10.2f%%", $p;
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;
231 printf "%-40s %10s %10s\n", ($key, $leaks, percentStr($percentLeaks));
232 $total += $leaks;
235 if (!$needsHeading) {
236 printf "%-40s %10s\n", ("TOTAL", $total);
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;
251 printf "%-40s %10s %10s\n", ($key, $leaks, percentStr($percentLeaks));
252 $total += $leaks;
255 if (!$needsHeading) {
256 printf "%-40s %10s\n", ("TOTAL", $total);
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;
271 printf "%-40s %10s %10s\n", ($key, $bloat, percentStr($percentBloat));
272 $total += $bloat;
275 if (!$needsHeading) {
276 printf "%-40s %10s\n", ("TOTAL", $total);
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;
291 printf "%-40s %10s %10s\n", ($key, $leaks, percentStr($percentLeaks));
292 if ($key !~ /TOTAL/) {
293 $total += $leaks;
297 if (!$needsHeading) {
298 # printf "%-40s %10s\n", ("TOTAL", $total);
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;
313 printf "%-40s %10s %10s\n", ($key, $bloat, percentStr($percentBloat));
314 if ($key !~ /TOTAL/) {
315 $total += $bloat;
319 if (!$needsHeading) {
320 # printf "%-40s %10s\n", ("TOTAL", $total);
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;
337 printf "%-40s %10s %10s\n", ($key, $leaks, $bloat);
338 if ($key !~ /TOTAL/) {
339 $ltotal += $leaks;
340 $btotal += $bloat;
344 if (!$needsHeading) {
345 printf "%-40s %10s %10s\n", ("TOTAL", $ltotal, $btotal);
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;
361 printf "%-40s %10s %10s\n", ($key, $leaks, $bloat);
362 if ($key !~ /TOTAL/) {
363 $ltotal += $leaks;
364 $btotal += $bloat;
368 if (!$needsHeading) {
369 printf "%-40s %10s %10s\n", ("TOTAL", $ltotal, $btotal);
372 print "--------------------------------------------------------------------------------------\n";