| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # | 2 # |
| 3 # Copyright 2010 the V8 project authors. All rights reserved. | 3 # Copyright 2010 the V8 project authors. All rights reserved. |
| 4 # Redistribution and use in source and binary forms, with or without | 4 # Redistribution and use in source and binary forms, with or without |
| 5 # modification, are permitted provided that the following conditions are | 5 # modification, are permitted provided that the following conditions are |
| 6 # met: | 6 # met: |
| 7 # | 7 # |
| 8 # * Redistributions of source code must retain the above copyright | 8 # * Redistributions of source code must retain the above copyright |
| 9 # notice, this list of conditions and the following disclaimer. | 9 # notice, this list of conditions and the following disclaimer. |
| 10 # * Redistributions in binary form must reproduce the above | 10 # * Redistributions in binary form must reproduce the above |
| (...skipping 29 matching lines...) Expand all Loading... |
| 40 from __future__ import with_statement | 40 from __future__ import with_statement |
| 41 import sys, types, re, subprocess | 41 import sys, types, re, subprocess |
| 42 | 42 |
| 43 def flatten(l): | 43 def flatten(l): |
| 44 flat = [] | 44 flat = [] |
| 45 for i in l: flat.extend(i) | 45 for i in l: flat.extend(i) |
| 46 return flat | 46 return flat |
| 47 | 47 |
| 48 def split_nvp(s): | 48 def split_nvp(s): |
| 49 t = {} | 49 t = {} |
| 50 for m in re.finditer(r"(\w+)=(-?\d+)", s): | 50 for (name, value) in re.findall(r"(\w+)=([-\w]+)", s): |
| 51 t[m.group(1)] = int(m.group(2)) | 51 try: |
| 52 t[name] = int(value) |
| 53 except ValueError: |
| 54 t[name] = value |
| 55 |
| 52 return t | 56 return t |
| 53 | 57 |
| 54 def parse_gc_trace(input): | 58 def parse_gc_trace(input): |
| 55 trace = [] | 59 trace = [] |
| 56 with open(input) as f: | 60 with open(input) as f: |
| 57 for line in f: | 61 for line in f: |
| 58 info = split_nvp(line) | 62 info = split_nvp(line) |
| 59 if info and 'pause' in info and info['pause'] > 0: | 63 if info and 'pause' in info and info['pause'] > 0: |
| 60 info['i'] = len(trace) | 64 info['i'] = len(trace) |
| 61 trace.append(info) | 65 trace.append(info) |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 204 charts.append(outfilename) | 208 charts.append(outfilename) |
| 205 script = generate_script_and_datafile(plot, trace, '~datafile', outfilename) | 209 script = generate_script_and_datafile(plot, trace, '~datafile', outfilename) |
| 206 print 'Plotting %s...' % outfilename | 210 print 'Plotting %s...' % outfilename |
| 207 gnuplot(script) | 211 gnuplot(script) |
| 208 | 212 |
| 209 return charts | 213 return charts |
| 210 | 214 |
| 211 def reclaimed_bytes(row): | 215 def reclaimed_bytes(row): |
| 212 return row['total_size_before'] - row['total_size_after'] | 216 return row['total_size_before'] - row['total_size_after'] |
| 213 | 217 |
| 218 def other_scope(r): |
| 219 return r['pause'] - r['mark'] - r['sweep'] - r['compact'] - r['flushcode'] |
| 220 |
| 214 plots = [ | 221 plots = [ |
| 215 [ | 222 [ |
| 216 Set('style fill solid 0.5 noborder'), | 223 Set('style fill solid 0.5 noborder'), |
| 217 Set('style histogram rowstacked'), | 224 Set('style histogram rowstacked'), |
| 218 Set('style data histograms'), | 225 Set('style data histograms'), |
| 219 Plot(Item('Marking', 'mark', lc = 'purple'), | 226 Plot(Item('Marking', 'mark', lc = 'purple'), |
| 220 Item('Sweep', 'sweep', lc = 'blue'), | 227 Item('Sweep', 'sweep', lc = 'blue'), |
| 221 Item('Compaction', 'compact', lc = 'red'), | 228 Item('Compaction', 'compact', lc = 'red'), |
| 222 Item('Other', | 229 Item('Flush Code', 'flushcode', lc = 'yellow'), |
| 223 lambda r: r['pause'] - r['mark'] - r['sweep'] - r['compact'], | 230 Item('Other', other_scope, lc = 'grey')) |
| 224 lc = 'grey')) | |
| 225 ], | 231 ], |
| 226 [ | 232 [ |
| 227 Set('style histogram rowstacked'), | 233 Set('style histogram rowstacked'), |
| 228 Set('style data histograms'), | 234 Set('style data histograms'), |
| 229 Plot(Item('Heap Size (before GC)', 'total_size_before', x1y2, | 235 Plot(Item('Heap Size (before GC)', 'total_size_before', x1y2, |
| 230 fs = 'solid 0.4 noborder', | 236 fs = 'solid 0.4 noborder', |
| 231 lc = 'green'), | 237 lc = 'green'), |
| 232 Item('Total holes (after GC)', 'holes_size_before', x1y2, | 238 Item('Total holes (after GC)', 'holes_size_before', x1y2, |
| 233 fs = 'solid 0.4 noborder', | 239 fs = 'solid 0.4 noborder', |
| 234 lc = 'red'), | 240 lc = 'red'), |
| (...skipping 14 matching lines...) Expand all Loading... |
| 249 ], | 255 ], |
| 250 [ | 256 [ |
| 251 Set('style fill solid 0.5 noborder'), | 257 Set('style fill solid 0.5 noborder'), |
| 252 Set('style data histograms'), | 258 Set('style data histograms'), |
| 253 Plot(Item('Allocated', 'allocated'), | 259 Plot(Item('Allocated', 'allocated'), |
| 254 Item('Reclaimed', reclaimed_bytes), | 260 Item('Reclaimed', reclaimed_bytes), |
| 255 Item('Promoted', 'promoted', style = 'lines', lc = 'black')) | 261 Item('Promoted', 'promoted', style = 'lines', lc = 'black')) |
| 256 ], | 262 ], |
| 257 ] | 263 ] |
| 258 | 264 |
| 265 def calc_total(trace, field): |
| 266 return reduce(lambda t,r: t + r[field], trace, 0) |
| 267 |
| 268 def calc_max(trace, field): |
| 269 return reduce(lambda t,r: max(t, r[field]), trace, 0) |
| 270 |
| 259 def process_trace(filename): | 271 def process_trace(filename): |
| 260 trace = parse_gc_trace(filename) | 272 trace = parse_gc_trace(filename) |
| 261 total_gc = reduce(lambda t,r: t + r['pause'], trace, 0) | 273 total_gc = calc_total(trace, 'pause') |
| 262 max_gc = reduce(lambda t,r: max(t, r['pause']), trace, 0) | 274 max_gc = calc_max(trace, 'pause') |
| 263 avg_gc = total_gc / len(trace) | 275 avg_gc = total_gc / len(trace) |
| 264 | 276 |
| 277 total_sweep = calc_total(trace, 'sweep') |
| 278 max_sweep = calc_max(trace, 'sweep') |
| 279 |
| 280 total_mark = calc_total(trace, 'mark') |
| 281 max_mark = calc_max(trace, 'mark') |
| 282 |
| 283 scavenges = filter(lambda r: r['gc'] == 's', trace) |
| 284 total_scavenge = calc_total(scavenges, 'pause') |
| 285 max_scavenge = calc_max(scavenges, 'pause') |
| 286 avg_scavenge = total_scavenge / len(scavenges) |
| 287 |
| 265 charts = plot_all(plots, trace, filename) | 288 charts = plot_all(plots, trace, filename) |
| 266 | 289 |
| 267 with open(filename + '.html', 'w') as out: | 290 with open(filename + '.html', 'w') as out: |
| 268 out.write('<html><body>') | 291 out.write('<html><body>') |
| 292 out.write('<table><tr><td>') |
| 269 out.write('Total in GC: <b>%d</b><br/>' % total_gc) | 293 out.write('Total in GC: <b>%d</b><br/>' % total_gc) |
| 270 out.write('Max in GC: <b>%d</b><br/>' % max_gc) | 294 out.write('Max in GC: <b>%d</b><br/>' % max_gc) |
| 271 out.write('Avg in GC: <b>%d</b><br/>' % avg_gc) | 295 out.write('Avg in GC: <b>%d</b><br/>' % avg_gc) |
| 296 out.write('</td><td>') |
| 297 out.write('Total in Scavenge: <b>%d</b><br/>' % total_scavenge) |
| 298 out.write('Max in Scavenge: <b>%d</b><br/>' % max_scavenge) |
| 299 out.write('Avg in Scavenge: <b>%d</b><br/>' % avg_scavenge) |
| 300 out.write('</td><td>') |
| 301 out.write('Total in Sweep: <b>%d</b><br/>' % total_sweep) |
| 302 out.write('Max in Sweep: <b>%d</b><br/>' % max_sweep) |
| 303 out.write('</td><td>') |
| 304 out.write('Total in Mark: <b>%d</b><br/>' % total_mark) |
| 305 out.write('Max in Mark: <b>%d</b><br/>' % max_mark) |
| 306 out.write('</td></tr></table>') |
| 272 for chart in charts: | 307 for chart in charts: |
| 273 out.write('<img src="%s">' % chart) | 308 out.write('<img src="%s">' % chart) |
| 274 out.write('</body></html>') | 309 out.write('</body></html>') |
| 275 | 310 |
| 276 print "%s generated." % (filename + '.html') | 311 print "%s generated." % (filename + '.html') |
| 277 | 312 |
| 278 if len(sys.argv) != 2: | 313 if len(sys.argv) != 2: |
| 279 print "Usage: %s <GC-trace-filename>" % sys.argv[0] | 314 print "Usage: %s <GC-trace-filename>" % sys.argv[0] |
| 280 sys.exit(1) | 315 sys.exit(1) |
| 281 | 316 |
| 282 process_trace(sys.argv[1]) | 317 process_trace(sys.argv[1]) |
| OLD | NEW |