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 |