| 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, math | 41 import sys, types, subprocess, math |
| 42 import gc_nvp_common |
| 42 | 43 |
| 43 def flatten(l): | 44 def flatten(l): |
| 44 flat = [] | 45 flat = [] |
| 45 for i in l: flat.extend(i) | 46 for i in l: flat.extend(i) |
| 46 return flat | 47 return flat |
| 47 | 48 |
| 48 def split_nvp(s): | |
| 49 t = {} | |
| 50 for (name, value) in re.findall(r"(\w+)=([-\w]+)", s): | |
| 51 try: | |
| 52 t[name] = int(value) | |
| 53 except ValueError: | |
| 54 t[name] = value | |
| 55 | |
| 56 return t | |
| 57 | |
| 58 def parse_gc_trace(input): | |
| 59 trace = [] | |
| 60 with open(input) as f: | |
| 61 for line in f: | |
| 62 info = split_nvp(line) | |
| 63 if info and 'pause' in info and info['pause'] > 0: | |
| 64 info['i'] = len(trace) | |
| 65 trace.append(info) | |
| 66 return trace | |
| 67 | |
| 68 def extract_field_names(script): | |
| 69 fields = { 'data': true, 'in': true } | |
| 70 | |
| 71 for m in re.finditer(r"$(\w+)", script): | |
| 72 field_name = m.group(1) | |
| 73 if field_name not in fields: | |
| 74 fields[field] = field_count | |
| 75 field_count = field_count + 1 | |
| 76 | |
| 77 return fields | |
| 78 | |
| 79 def gnuplot(script): | 49 def gnuplot(script): |
| 80 gnuplot = subprocess.Popen(["gnuplot"], stdin=subprocess.PIPE) | 50 gnuplot = subprocess.Popen(["gnuplot"], stdin=subprocess.PIPE) |
| 81 gnuplot.stdin.write(script) | 51 gnuplot.stdin.write(script) |
| 82 gnuplot.stdin.close() | 52 gnuplot.stdin.close() |
| 83 gnuplot.wait() | 53 gnuplot.wait() |
| 84 | 54 |
| 85 x1y1 = 'x1y1' | 55 x1y1 = 'x1y1' |
| 86 x1y2 = 'x1y2' | 56 x1y2 = 'x1y2' |
| 87 x2y1 = 'x2y1' | 57 x2y1 = 'x2y1' |
| 88 x2y2 = 'x2y2' | 58 x2y2 = 'x2y2' |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 221 return 0 | 191 return 0 |
| 222 return r['pause'] - r['mark'] - r['sweep'] - r['external'] | 192 return r['pause'] - r['mark'] - r['sweep'] - r['external'] |
| 223 | 193 |
| 224 def scavenge_scope(r): | 194 def scavenge_scope(r): |
| 225 if r['gc'] == 's': | 195 if r['gc'] == 's': |
| 226 return r['pause'] - r['external'] | 196 return r['pause'] - r['external'] |
| 227 return 0 | 197 return 0 |
| 228 | 198 |
| 229 | 199 |
| 230 def real_mutator(r): | 200 def real_mutator(r): |
| 231 return r['mutator'] - r['stepstook'] | 201 return r['mutator'] - r['steps_took'] |
| 232 | 202 |
| 233 plots = [ | 203 plots = [ |
| 234 [ | 204 [ |
| 235 Set('style fill solid 0.5 noborder'), | 205 Set('style fill solid 0.5 noborder'), |
| 236 Set('style histogram rowstacked'), | 206 Set('style histogram rowstacked'), |
| 237 Set('style data histograms'), | 207 Set('style data histograms'), |
| 238 Plot(Item('Scavenge', scavenge_scope, lc = 'green'), | 208 Plot(Item('Scavenge', scavenge_scope, lc = 'green'), |
| 239 Item('Marking', 'mark', lc = 'purple'), | 209 Item('Marking', 'mark', lc = 'purple'), |
| 240 Item('Sweep', 'sweep', lc = 'blue'), | 210 Item('Sweep', 'sweep', lc = 'blue'), |
| 241 Item('External', 'external', lc = '#489D43'), | 211 Item('External', 'external', lc = '#489D43'), |
| 242 Item('Other', other_scope, lc = 'grey'), | 212 Item('Other', other_scope, lc = 'grey'), |
| 243 Item('IGC Steps', 'stepstook', lc = '#FF6347')) | 213 Item('IGC Steps', 'steps_took', lc = '#FF6347')) |
| 244 ], | 214 ], |
| 245 [ | 215 [ |
| 246 Set('style fill solid 0.5 noborder'), | 216 Set('style fill solid 0.5 noborder'), |
| 247 Set('style histogram rowstacked'), | 217 Set('style histogram rowstacked'), |
| 248 Set('style data histograms'), | 218 Set('style data histograms'), |
| 249 Plot(Item('Scavenge', scavenge_scope, lc = 'green'), | 219 Plot(Item('Scavenge', scavenge_scope, lc = 'green'), |
| 250 Item('Marking', 'mark', lc = 'purple'), | 220 Item('Marking', 'mark', lc = 'purple'), |
| 251 Item('Sweep', 'sweep', lc = 'blue'), | 221 Item('Sweep', 'sweep', lc = 'blue'), |
| 252 Item('External', 'external', lc = '#489D43'), | 222 Item('External', 'external', lc = '#489D43'), |
| 253 Item('Other', other_scope, lc = '#ADD8E6'), | 223 Item('Other', other_scope, lc = '#ADD8E6'), |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 297 return freduce(lambda t,v: t + long(v), field, trace, long(0)) | 267 return freduce(lambda t,v: t + long(v), field, trace, long(0)) |
| 298 | 268 |
| 299 def calc_max(trace, field): | 269 def calc_max(trace, field): |
| 300 return freduce(lambda t,r: max(t, r), field, trace, 0) | 270 return freduce(lambda t,r: max(t, r), field, trace, 0) |
| 301 | 271 |
| 302 def count_nonzero(trace, field): | 272 def count_nonzero(trace, field): |
| 303 return freduce(lambda t,r: t if r == 0 else t + 1, field, trace, 0) | 273 return freduce(lambda t,r: t if r == 0 else t + 1, field, trace, 0) |
| 304 | 274 |
| 305 | 275 |
| 306 def process_trace(filename): | 276 def process_trace(filename): |
| 307 trace = parse_gc_trace(filename) | 277 trace = gc_nvp_common.parse_gc_trace(filename) |
| 308 | 278 |
| 309 marksweeps = filter(lambda r: r['gc'] == 'ms', trace) | 279 marksweeps = filter(lambda r: r['gc'] == 'ms', trace) |
| 310 scavenges = filter(lambda r: r['gc'] == 's', trace) | 280 scavenges = filter(lambda r: r['gc'] == 's', trace) |
| 311 globalgcs = filter(lambda r: r['gc'] != 's', trace) | 281 globalgcs = filter(lambda r: r['gc'] != 's', trace) |
| 312 | 282 |
| 313 | 283 |
| 314 charts = plot_all(plots, trace, filename) | 284 charts = plot_all(plots, trace, filename) |
| 315 | 285 |
| 316 def stats(out, prefix, trace, field): | 286 def stats(out, prefix, trace, field): |
| 317 n = len(trace) | 287 n = len(trace) |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 380 out.write('<img src="%s">' % chart) | 350 out.write('<img src="%s">' % chart) |
| 381 out.write('</body></html>') | 351 out.write('</body></html>') |
| 382 | 352 |
| 383 print "%s generated." % (filename + '.html') | 353 print "%s generated." % (filename + '.html') |
| 384 | 354 |
| 385 if len(sys.argv) != 2: | 355 if len(sys.argv) != 2: |
| 386 print "Usage: %s <GC-trace-filename>" % sys.argv[0] | 356 print "Usage: %s <GC-trace-filename>" % sys.argv[0] |
| 387 sys.exit(1) | 357 sys.exit(1) |
| 388 | 358 |
| 389 process_trace(sys.argv[1]) | 359 process_trace(sys.argv[1]) |
| OLD | NEW |