Chromium Code Reviews| 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 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 258 Plot(Item('Allocated', 'allocated'), | 258 Plot(Item('Allocated', 'allocated'), |
| 259 Item('Reclaimed', reclaimed_bytes), | 259 Item('Reclaimed', reclaimed_bytes), |
| 260 Item('Promoted', 'promoted', style = 'lines', lc = 'black')) | 260 Item('Promoted', 'promoted', style = 'lines', lc = 'black')) |
| 261 ], | 261 ], |
| 262 ] | 262 ] |
| 263 | 263 |
| 264 def freduce(f, field, trace, init): | 264 def freduce(f, field, trace, init): |
| 265 return reduce(lambda t,r: f(t, r[field]), trace, init) | 265 return reduce(lambda t,r: f(t, r[field]), trace, init) |
| 266 | 266 |
| 267 def calc_total(trace, field): | 267 def calc_total(trace, field): |
| 268 return freduce(lambda t,v: t + v, field, trace, 0) | 268 return freduce(lambda t,v: t + long(v), field, trace, long(0)) |
| 269 | 269 |
| 270 def calc_max(trace, field): | 270 def calc_max(trace, field): |
| 271 return freduce(lambda t,r: max(t, r), field, trace, 0) | 271 return freduce(lambda t,r: max(t, r), field, trace, 0) |
| 272 | 272 |
| 273 def count_nonzero(trace, field): | 273 def count_nonzero(trace, field): |
| 274 return freduce(lambda t,r: t if r == 0 else t + 1, field, trace, 0) | 274 return freduce(lambda t,r: t if r == 0 else t + 1, field, trace, 0) |
| 275 | 275 |
| 276 | 276 |
| 277 def process_trace(filename): | 277 def process_trace(filename): |
| 278 trace = parse_gc_trace(filename) | 278 trace = parse_gc_trace(filename) |
| 279 | 279 |
| 280 marksweeps = filter(lambda r: r['gc'] == 'ms', trace) | 280 marksweeps = filter(lambda r: r['gc'] == 'ms', trace) |
| 281 markcompacts = filter(lambda r: r['gc'] == 'mc', trace) | 281 markcompacts = filter(lambda r: r['gc'] == 'mc', trace) |
| 282 scavenges = filter(lambda r: r['gc'] == 's', trace) | 282 scavenges = filter(lambda r: r['gc'] == 's', trace) |
| 283 globalgcs = filter(lambda r: r['gc'] != 's', trace) | |
| 284 | |
| 283 | 285 |
| 284 charts = plot_all(plots, trace, filename) | 286 charts = plot_all(plots, trace, filename) |
| 285 | 287 |
| 286 def stats(out, prefix, trace, field): | 288 def stats(out, prefix, trace, field): |
| 287 n = len(trace) | 289 n = len(trace) |
| 288 total = calc_total(trace, field) | 290 total = calc_total(trace, field) |
| 289 max = calc_max(trace, field) | 291 max = calc_max(trace, field) |
| 290 if n > 0: | 292 if n > 0: |
| 291 avg = total / n | 293 avg = total / n |
| 292 else: | 294 else: |
| 293 avg = 0 | 295 avg = 0 |
| 294 if n > 1: | 296 if n > 1: |
| 295 dev = math.sqrt(freduce(lambda t,r: (r - avg) ** 2, field, trace, 0) / | 297 dev = math.sqrt(freduce(lambda t,r: t + (r - avg) ** 2, field, trace, 0) / |
| 296 (n - 1)) | 298 (n - 1)) |
| 297 else: | 299 else: |
| 298 dev = 0 | 300 dev = 0 |
| 299 | 301 |
| 300 out.write('<tr><td>%s</td><td>%d</td><td>%d</td>' | 302 out.write('<tr><td>%s</td><td>%d</td><td>%d</td>' |
| 301 '<td>%d</td><td>%d [dev %f]</td></tr>' % | 303 '<td>%d</td><td>%d [dev %f]</td></tr>' % |
| 302 (prefix, n, total, max, avg, dev)) | 304 (prefix, n, total, max, avg, dev)) |
| 303 | 305 |
| 306 def HumanReadable(size): | |
| 307 suffixes = ['B', 'KB', 'MB', 'GB'] | |
|
Erik Corry
2011/01/10 12:21:07
K -> k
I also prefer bytes to B since B is a measu
| |
| 308 power = 1 | |
| 309 for i in range(len(suffixes)): | |
| 310 if size < power*1024: | |
| 311 return "%.1f" % (float(size) / power) + " " + suffixes[i] | |
| 312 power *= 1024 | |
| 313 | |
| 314 def throughput(name, trace): | |
| 315 total_live_after = calc_total(trace, 'total_size_after') | |
| 316 total_live_before = calc_total(trace, 'total_size_before') | |
| 317 total_gc = calc_total(trace, 'pause') | |
| 318 out.write('GC %s Throughput (after): %s / %s ms = %s/ms<br/>' % | |
| 319 (name, | |
| 320 HumanReadable(total_live_after), | |
| 321 total_gc, | |
| 322 HumanReadable(total_live_after / total_gc))) | |
|
Erik Corry
2011/01/10 12:21:07
Should we check for total_gc being zero?
| |
| 323 out.write('GC %s Throughput (before): %s / %s ms = %s/ms<br/>' % | |
| 324 (name, | |
| 325 HumanReadable(total_live_before), | |
| 326 total_gc, | |
| 327 HumanReadable(total_live_before / total_gc))) | |
| 328 | |
| 304 | 329 |
| 305 with open(filename + '.html', 'w') as out: | 330 with open(filename + '.html', 'w') as out: |
| 306 out.write('<html><body>') | 331 out.write('<html><body>') |
| 307 out.write('<table>') | 332 out.write('<table>') |
| 308 out.write('<tr><td>Phase</td><td>Count</td><td>Time (ms)</td>') | 333 out.write('<tr><td>Phase</td><td>Count</td><td>Time (ms)</td>') |
| 309 out.write('<td>Max</td><td>Avg</td></tr>') | 334 out.write('<td>Max</td><td>Avg</td></tr>') |
| 310 stats(out, 'Total in GC', trace, 'pause') | 335 stats(out, 'Total in GC', trace, 'pause') |
| 311 stats(out, 'Scavenge', scavenges, 'pause') | 336 stats(out, 'Scavenge', scavenges, 'pause') |
| 312 stats(out, 'MarkSweep', marksweeps, 'pause') | 337 stats(out, 'MarkSweep', marksweeps, 'pause') |
| 313 stats(out, 'MarkCompact', markcompacts, 'pause') | 338 stats(out, 'MarkCompact', markcompacts, 'pause') |
| 314 stats(out, 'Mark', filter(lambda r: r['mark'] != 0, trace), 'mark') | 339 stats(out, 'Mark', filter(lambda r: r['mark'] != 0, trace), 'mark') |
| 315 stats(out, 'Sweep', filter(lambda r: r['sweep'] != 0, trace), 'sweep') | 340 stats(out, 'Sweep', filter(lambda r: r['sweep'] != 0, trace), 'sweep') |
| 316 stats(out, 'Compact', filter(lambda r: r['compact'] != 0, trace), 'compact') | 341 stats(out, 'Compact', filter(lambda r: r['compact'] != 0, trace), 'compact') |
| 317 out.write('</table>') | 342 out.write('</table>') |
| 343 throughput('TOTAL', trace) | |
| 344 throughput('MS', marksweeps) | |
|
Erik Corry
2011/01/10 12:21:07
This seems excessively concise.
| |
| 345 throughput('MC', markcompacts) | |
| 346 throughput('OLDSPACE', globalgcs) | |
| 347 out.write('<br/>') | |
| 318 for chart in charts: | 348 for chart in charts: |
| 319 out.write('<img src="%s">' % chart) | 349 out.write('<img src="%s">' % chart) |
| 320 out.write('</body></html>') | 350 out.write('</body></html>') |
| 321 | 351 |
| 322 print "%s generated." % (filename + '.html') | 352 print "%s generated." % (filename + '.html') |
| 323 | 353 |
| 324 if len(sys.argv) != 2: | 354 if len(sys.argv) != 2: |
| 325 print "Usage: %s <GC-trace-filename>" % sys.argv[0] | 355 print "Usage: %s <GC-trace-filename>" % sys.argv[0] |
| 326 sys.exit(1) | 356 sys.exit(1) |
| 327 | 357 |
| 328 process_trace(sys.argv[1]) | 358 process_trace(sys.argv[1]) |
| OLD | NEW |