3 # Subroutines to parses a ghc Garbage Collection stats file
5 #%gcstats = &parse_stats($ARGV[0]);
6 #&print_stats(">-", %gcstats);
11 return($1 * 1000000000 + $2 * 1000000 + $3 * 1000 + $4)
12 if ( $text =~ /^(\d*),(\d*),(\d*),(\d*)$/ );
13 return($1 * 1000000 + $2 * 1000 + $3)
14 if ( $text =~ /^(\d*),(\d*),(\d*)$/ );
15 return($1 * 1000 + $2)
16 if ( $text =~ /^(\d*),(\d*)$/ );
18 if ( $text =~ /^(\d*)$/ );
19 die "Error converting $text\n";
24 local ($b, $m, $t, $o) = (int($num/1000000000), int($num/1000000)%1000,
25 int($num/1000)%1000, $num%1000);
26 return(sprintf("%d,%03d,%03d,%03d", $b, $m, $t, $o)) if $b > 0;
27 return(sprintf("%d,%03d,%03d", $m, $t, $o)) if $m > 0;
28 return(sprintf("%d,%03d", $t, $o)) if $t > 0;
29 return(sprintf("%d", $o)) if $o > 0;
33 local($filename) = @_;
34 local($tot_alloc, $tot_gc_user, $tot_mut_user, $tot_user,
35 $tot_gc_elap, $tot_mut_elap, $tot_elap);
36 local($statsfile, $line, $row, $col, $val);
37 local(@stats, @hdr1, @hdr2, @line_vals);
41 open(STATS, $filename) || die "Cant open $filename \n";
44 do {$line = shift(@stats);} until ($line !~ /^$/);
46 ($the_stats{"command"}, $the_stats{"args"}) = split(' ', $line, 2);
48 do {$line = shift(@stats);} until ($line !~ /^$/);
49 $line =~ /Collector:\s*([A-Z]+)\s*HeapSize:\s*([\d,]+)/;
50 $the_stats{"collector"} = $1;
51 $the_stats{"heapsize"} = &to_num($2);
53 do {$line = shift(@stats);} until ($line !~ /^$/);
55 @hdr1 = split(' ', $line);
56 $line = shift(@stats);
58 @hdr2 = split(' ', $line);
69 while (($line = shift(@stats)) !~ /^\s*\d+\s*$/) {
71 @line_vals = split(' ', $line);
75 while(++$col <= $#line_vals) {
77 $val = $line_vals[$col];
78 $_ = @hdr1[$col] . @hdr2[$col];
80 /^Allocbytes$/ && do { $tot_alloc += $val;
81 $the_stats{"alloc_$row"} = $val;
84 /^Collectbytes$/ && do { $the_stats{"collect_$row"} = $val;
87 /^Livebytes$/ && do { $the_stats{"live_$row"} = $val;
90 /^Residency$/ && do { next word; };
92 /^GCuser$/ && do { $tot_gc_user += $val;
93 $the_stats{"gc_user_$row"} = $val;
96 /^GCelap$/ && do { $tot_gc_elap += $val;
97 $the_stats{"gc_elap_$row"} = $val;
100 /^TOTuser$/ && do { $the_stats{"mut_user_$row"} =
101 $val - $tot_user - $the_stats{"gc_user_$row"};
102 $tot_mut_user += $the_stats{"mut_user_$row"};
106 /^TOTelap$/ && do { $the_stats{"mut_elap_$row"} =
107 $val - $tot_elap - $the_stats{"gc_elap_$row"};
108 $tot_mut_elap += $the_stats{"mut_elap_$row"};
112 /^PageGC$/ && do { $the_stats{"gc_pflts_$row"} = $val;
115 /^FltsMUT$/ && do { $the_stats{"mut_pflts_$row"} = $val;
118 /^Collection/ && do { $the_stats{"mode_$row"} = $val;
121 /^Astkbytes$/ && do {next word; };
122 /^Bstkbytes$/ && do {next word; };
123 /^CafNo$/ && do {next word; };
124 /^Cafbytes$/ && do {next word; };
126 /^NoAstk$/ && do {next word; };
127 /^ofBstk$/ && do {next word; };
128 /^RootsReg$/ && do {next word; };
129 /^OldGen$/ && do {next word; };
130 /^RootsCaf$/ && do {next word; };
131 /^Sizebytes$/ && do {next word; };
132 /^Resid\%heap$/ && do {next word; };
134 /^$/ && do {next word; };
136 print STDERR "Unknown: $_ = $val\n";
142 $the_stats{"alloc_$row"} = $line;
144 arg: while($_ = $stats[0]) {
147 /^\s*([\d,]+) bytes alloc/ && do { local($a) = &to_num($1);
148 $a == $tot_alloc || die "Total $a != $tot_alloc \n";
149 $the_stats{"alloc_total"} = $tot_alloc;
152 /^\s*([\d]+) garbage/ && do { $1 == $row || die "GCNo $1 != $row \n";
153 $the_stats{"gc_no"} = $row;
156 /Total time\s+([\d\.]+)s\s+\(\s*([\d.]+)s elapsed\)/ && do {
157 $the_stats{"user_total"} = $1;
158 $the_stats{"elap_total"} = $2;
159 $the_stats{"mut_user_total"} = $1 - $tot_gc_user;
160 $the_stats{"mut_elap_total"} = $2 - $tot_gc_elap;
161 $the_stats{"mut_user_$row"} = $1 - $tot_gc_user - $tot_mut_user;
162 $the_stats{"mut_elap_$row"} = $2 - $tot_gc_elap - $tot_mut_elap;
165 /GC\s+time\s+([\d\.]+)s\s+\(\s*([\d.]+)s elapsed\)/ && do {
166 # $1 == $tot_gc_user || die "GCuser $1 != $tot_gc_user \n";
167 # $2 == $tot_gc_elap || die "GCelap $2 != $tot_gc_elap \n";
168 $the_stats{"gc_user_total"} = $tot_gc_user;
169 $the_stats{"gc_elap_total"} = $tot_gc_elap;
172 /MUT\s+time/ && do { next arg; };
173 /INIT\s+time/ && do { next arg; };
174 /^\s*([\d,]+) bytes maximum residency/ && do { next arg; };
176 /\%GC time/ && do { next arg; };
177 /Alloc rate/ && do { next arg; };
178 /Productivity/ && do { next arg; };
179 /^$/ && do { next arg; };
180 /^\#/ && do { next arg; }; # Allows comments to follow
182 print STDERR "Unmatched line: $_";
190 local ($filename, %out_stats) = @_;
191 local($statsfile, $row);
193 open($statsfile, $filename) || die "Cant open $filename \n";
196 print $out_stats{"command"}, " ", $out_stats{"args"}, "\n\n";
197 print "Collector: ", $out_stats{"collector"}, " HeapSize: ", &from_num($out_stats{"heapsize"}), " (bytes)\n\n";
200 while ($row < $out_stats{"gc_no"}) {
201 printf "%7d %7d %7d %5.2f %5.2f %5.2f %5.2f %4d %4d %s\n",
202 $out_stats{"alloc_$row"},
203 $out_stats{"collect_$row"},
204 $out_stats{"live_$row"},
205 $out_stats{"gc_user_$row"},
206 $out_stats{"gc_elap_$row"},
207 $out_stats{"mut_user_$row"},
208 $out_stats{"mut_elap_$row"},
209 $out_stats{"gc_pflts_$row"},
210 $out_stats{"mut_pflts_$row"},
211 $out_stats{"mode_$row"};
214 printf "%7d %s %5.2f %5.2f \n\n",
215 $out_stats{"alloc_$row"}, " " x 27,
216 $out_stats{"mut_user_$row"},
217 $out_stats{"mut_elap_$row"};
219 printf "Total Alloc: %s\n", &from_num($out_stats{"alloc_total"});
220 printf " GC No: %d\n\n", $out_stats{"gc_no"};
222 printf " MUT User: %6.2fs\n", $out_stats{"mut_user_total"};
223 printf " GC User: %6.2fs\n", $out_stats{"gc_user_total"};
224 printf "Total User: %6.2fs\n\n", $out_stats{"user_total"};
226 printf " MUT Elap: %6.2fs\n", $out_stats{"mut_elap_total"};
227 printf " GC Elap: %6.2fs\n", $out_stats{"gc_elap_total"};
228 printf "Total Elap: %6.2fs\n", $out_stats{"elap_total"};