| 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 20 matching lines...) Expand all  Loading... | 
|   31 # |   31 # | 
|   32 # This is an utility for plotting charts based on GC traces produced by V8 when |   32 # This is an utility for plotting charts based on GC traces produced by V8 when | 
|   33 # run with flags --trace-gc --trace-gc-nvp. Relies on gnuplot for actual |   33 # run with flags --trace-gc --trace-gc-nvp. Relies on gnuplot for actual | 
|   34 # plotting. |   34 # plotting. | 
|   35 # |   35 # | 
|   36 # Usage: gc-nvp-trace-processor.py <GC-trace-filename> |   36 # Usage: gc-nvp-trace-processor.py <GC-trace-filename> | 
|   37 # |   37 # | 
|   38  |   38  | 
|   39  |   39  | 
|   40 from __future__ import with_statement |   40 from __future__ import with_statement | 
|   41 import sys, types, re, subprocess |   41 import sys, types, re, subprocess, math | 
|   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 (name, value) in re.findall(r"(\w+)=([-\w]+)", s): |   50   for (name, value) in re.findall(r"(\w+)=([-\w]+)", s): | 
|   51     try: |   51     try: | 
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  255   ], |  255   ], | 
|  256   [ |  256   [ | 
|  257     Set('style fill solid 0.5 noborder'), |  257     Set('style fill solid 0.5 noborder'), | 
|  258     Set('style data histograms'), |  258     Set('style data histograms'), | 
|  259     Plot(Item('Allocated', 'allocated'), |  259     Plot(Item('Allocated', 'allocated'), | 
|  260          Item('Reclaimed', reclaimed_bytes), |  260          Item('Reclaimed', reclaimed_bytes), | 
|  261          Item('Promoted', 'promoted', style = 'lines', lc = 'black')) |  261          Item('Promoted', 'promoted', style = 'lines', lc = 'black')) | 
|  262   ], |  262   ], | 
|  263 ] |  263 ] | 
|  264  |  264  | 
 |  265 def freduce(f, field, trace, init): | 
 |  266   return reduce(lambda t,r: f(t, r[field]), trace, init) | 
 |  267  | 
|  265 def calc_total(trace, field): |  268 def calc_total(trace, field): | 
|  266   return reduce(lambda t,r: t + r[field], trace, 0) |  269   return freduce(lambda t,v: t + v, field, trace, 0) | 
|  267  |  270  | 
|  268 def calc_max(trace, field): |  271 def calc_max(trace, field): | 
|  269   return reduce(lambda t,r: max(t, r[field]), trace, 0) |  272   return freduce(lambda t,r: max(t, r), field, trace, 0) | 
 |  273  | 
 |  274 def count_nonzero(trace, field): | 
 |  275   return freduce(lambda t,r: t if r == 0 else t + 1, field, trace, 0) | 
 |  276  | 
|  270  |  277  | 
|  271 def process_trace(filename): |  278 def process_trace(filename): | 
|  272   trace = parse_gc_trace(filename) |  279   trace = parse_gc_trace(filename) | 
|  273   total_gc = calc_total(trace, 'pause') |  | 
|  274   max_gc = calc_max(trace, 'pause') |  | 
|  275   avg_gc = total_gc / len(trace) |  | 
|  276  |  280  | 
|  277   total_sweep = calc_total(trace, 'sweep') |  281   marksweeps = filter(lambda r: r['gc'] == 'ms', trace) | 
|  278   max_sweep = calc_max(trace, 'sweep') |  282   markcompacts = filter(lambda r: r['gc'] == 'mc', trace) | 
|  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) |  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  |  284  | 
|  288   charts = plot_all(plots, trace, filename) |  285   charts = plot_all(plots, trace, filename) | 
|  289  |  286  | 
 |  287   def stats(out, prefix, trace, field): | 
 |  288     n = len(trace) | 
 |  289     total = calc_total(trace, field) | 
 |  290     max = calc_max(trace, field) | 
 |  291     avg = total / n | 
 |  292     if n > 1: | 
 |  293       dev = math.sqrt(freduce(lambda t,r: (r - avg) ** 2, field, trace, 0) / | 
 |  294                       (n - 1)) | 
 |  295     else: | 
 |  296       dev = 0 | 
 |  297  | 
 |  298     out.write('<tr><td>%s</td><td>%d</td><td>%d</td>' | 
 |  299               '<td>%d</td><td>%d [dev %f]</td></tr>' % | 
 |  300               (prefix, n, total, max, avg, dev)) | 
 |  301  | 
 |  302  | 
|  290   with open(filename + '.html', 'w') as out: |  303   with open(filename + '.html', 'w') as out: | 
|  291     out.write('<html><body>') |  304     out.write('<html><body>') | 
|  292     out.write('<table><tr><td>') |  305     out.write('<table>') | 
|  293     out.write('Total in GC: <b>%d</b><br/>' % total_gc) |  306     out.write('<tr><td>Phase</td><td>Count</td><td>Time (ms)</td><td>Max</td><td
     >Avg</td></tr>') | 
|  294     out.write('Max in GC: <b>%d</b><br/>' % max_gc) |  307     stats(out, 'Total in GC', trace, 'pause') | 
|  295     out.write('Avg in GC: <b>%d</b><br/>' % avg_gc) |  308     stats(out, 'Scavenge', scavenges, 'pause') | 
|  296     out.write('</td><td>') |  309     stats(out, 'MarkSweep', marksweeps, 'pause') | 
|  297     out.write('Total in Scavenge: <b>%d</b><br/>' % total_scavenge) |  310     stats(out, 'MarkCompact', markcompacts, 'pause') | 
|  298     out.write('Max in Scavenge: <b>%d</b><br/>' % max_scavenge) |  311     stats(out, 'Mark', filter(lambda r: r['mark'] != 0, trace), 'mark') | 
|  299     out.write('Avg in Scavenge: <b>%d</b><br/>' % avg_scavenge) |  312     stats(out, 'Sweep', filter(lambda r: r['sweep'] != 0, trace), 'sweep') | 
|  300     out.write('</td><td>') |  313     stats(out, 'Flush Code', filter(lambda r: r['flushcode'] != 0, trace), 'flus
     hcode') | 
|  301     out.write('Total in Sweep: <b>%d</b><br/>' % total_sweep) |  314     stats(out, 'Compact', filter(lambda r: r['compact'] != 0, trace), 'compact') | 
|  302     out.write('Max in Sweep: <b>%d</b><br/>' % max_sweep) |  315     out.write('</table>') | 
|  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>') |  | 
|  307     for chart in charts: |  316     for chart in charts: | 
|  308       out.write('<img src="%s">' % chart) |  317       out.write('<img src="%s">' % chart) | 
|  309       out.write('</body></html>') |  318       out.write('</body></html>') | 
|  310  |  319  | 
|  311   print "%s generated." % (filename + '.html') |  320   print "%s generated." % (filename + '.html') | 
|  312  |  321  | 
|  313 if len(sys.argv) != 2: |  322 if len(sys.argv) != 2: | 
|  314   print "Usage: %s <GC-trace-filename>" % sys.argv[0] |  323   print "Usage: %s <GC-trace-filename>" % sys.argv[0] | 
|  315   sys.exit(1) |  324   sys.exit(1) | 
|  316  |  325  | 
|  317 process_trace(sys.argv[1]) |  326 process_trace(sys.argv[1]) | 
| OLD | NEW |