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 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
219 if r['gc'] == 's': | 219 if r['gc'] == 's': |
220 # there is no 'other' scope for scavenging collections. | 220 # there is no 'other' scope for scavenging collections. |
221 return 0 | 221 return 0 |
222 return r['pause'] - r['mark'] - r['sweep'] - r['compact'] - r['external'] | 222 return r['pause'] - r['mark'] - r['sweep'] - r['compact'] - r['external'] |
223 | 223 |
224 def scavenge_scope(r): | 224 def scavenge_scope(r): |
225 if r['gc'] == 's': | 225 if r['gc'] == 's': |
226 return r['pause'] - r['external'] | 226 return r['pause'] - r['external'] |
227 return 0 | 227 return 0 |
228 | 228 |
| 229 |
| 230 def real_mutator(r): |
| 231 return r['mutator'] - r['stepstook'] |
| 232 |
229 plots = [ | 233 plots = [ |
230 [ | 234 [ |
231 Set('style fill solid 0.5 noborder'), | 235 Set('style fill solid 0.5 noborder'), |
232 Set('style histogram rowstacked'), | 236 Set('style histogram rowstacked'), |
233 Set('style data histograms'), | 237 Set('style data histograms'), |
234 Plot(Item('Scavenge', scavenge_scope, lc = 'green'), | 238 Plot(Item('Scavenge', scavenge_scope, lc = 'green'), |
235 Item('Marking', 'mark', lc = 'purple'), | 239 Item('Marking', 'mark', lc = 'purple'), |
236 Item('Sweep', 'sweep', lc = 'blue'), | 240 Item('Sweep', 'sweep', lc = 'blue'), |
237 Item('Compaction', 'compact', lc = 'red'), | 241 Item('Compaction', 'compact', lc = 'red'), |
238 Item('External', 'external', lc = '#489D43'), | 242 Item('External', 'external', lc = '#489D43'), |
239 Item('Other', other_scope, lc = 'grey')) | 243 Item('Other', other_scope, lc = 'grey'), |
| 244 Item('IGC Steps', 'stepstook', lc = '#FF6347')) |
| 245 ], |
| 246 [ |
| 247 Set('style fill solid 0.5 noborder'), |
| 248 Set('style histogram rowstacked'), |
| 249 Set('style data histograms'), |
| 250 Plot(Item('Scavenge', scavenge_scope, lc = 'green'), |
| 251 Item('Marking', 'mark', lc = 'purple'), |
| 252 Item('Sweep', 'sweep', lc = 'blue'), |
| 253 Item('Compaction', 'compact', lc = 'red'), |
| 254 Item('External', 'external', lc = '#489D43'), |
| 255 Item('Other', other_scope, lc = '#ADD8E6'), |
| 256 Item('External', 'external', lc = '#D3D3D3')) |
| 257 ], |
| 258 |
| 259 [ |
| 260 Plot(Item('Mutator', real_mutator, lc = 'black', style = 'lines')) |
240 ], | 261 ], |
241 [ | 262 [ |
242 Set('style histogram rowstacked'), | 263 Set('style histogram rowstacked'), |
243 Set('style data histograms'), | 264 Set('style data histograms'), |
244 Plot(Item('Heap Size (before GC)', 'total_size_before', x1y2, | 265 Plot(Item('Heap Size (before GC)', 'total_size_before', x1y2, |
245 fs = 'solid 0.4 noborder', | 266 fs = 'solid 0.4 noborder', |
246 lc = 'green'), | 267 lc = 'green'), |
247 Item('Total holes (after GC)', 'holes_size_before', x1y2, | 268 Item('Total holes (after GC)', 'holes_size_before', x1y2, |
248 fs = 'solid 0.4 noborder', | 269 fs = 'solid 0.4 noborder', |
249 lc = 'red'), | 270 lc = 'red'), |
(...skipping 18 matching lines...) Expand all Loading... |
268 Plot(Item('Allocated', 'allocated'), | 289 Plot(Item('Allocated', 'allocated'), |
269 Item('Reclaimed', reclaimed_bytes), | 290 Item('Reclaimed', reclaimed_bytes), |
270 Item('Promoted', 'promoted', style = 'lines', lc = 'black')) | 291 Item('Promoted', 'promoted', style = 'lines', lc = 'black')) |
271 ], | 292 ], |
272 ] | 293 ] |
273 | 294 |
274 def freduce(f, field, trace, init): | 295 def freduce(f, field, trace, init): |
275 return reduce(lambda t,r: f(t, r[field]), trace, init) | 296 return reduce(lambda t,r: f(t, r[field]), trace, init) |
276 | 297 |
277 def calc_total(trace, field): | 298 def calc_total(trace, field): |
278 return freduce(lambda t,v: t + v, field, trace, 0) | 299 return freduce(lambda t,v: t + long(v), field, trace, long(0)) |
279 | 300 |
280 def calc_max(trace, field): | 301 def calc_max(trace, field): |
281 return freduce(lambda t,r: max(t, r), field, trace, 0) | 302 return freduce(lambda t,r: max(t, r), field, trace, 0) |
282 | 303 |
283 def count_nonzero(trace, field): | 304 def count_nonzero(trace, field): |
284 return freduce(lambda t,r: t if r == 0 else t + 1, field, trace, 0) | 305 return freduce(lambda t,r: t if r == 0 else t + 1, field, trace, 0) |
285 | 306 |
286 | 307 |
287 def process_trace(filename): | 308 def process_trace(filename): |
288 trace = parse_gc_trace(filename) | 309 trace = parse_gc_trace(filename) |
289 | 310 |
290 marksweeps = filter(lambda r: r['gc'] == 'ms', trace) | 311 marksweeps = filter(lambda r: r['gc'] == 'ms', trace) |
291 markcompacts = filter(lambda r: r['gc'] == 'mc', trace) | 312 markcompacts = filter(lambda r: r['gc'] == 'mc', trace) |
292 scavenges = filter(lambda r: r['gc'] == 's', trace) | 313 scavenges = filter(lambda r: r['gc'] == 's', trace) |
| 314 globalgcs = filter(lambda r: r['gc'] != 's', trace) |
| 315 |
293 | 316 |
294 charts = plot_all(plots, trace, filename) | 317 charts = plot_all(plots, trace, filename) |
295 | 318 |
296 def stats(out, prefix, trace, field): | 319 def stats(out, prefix, trace, field): |
297 n = len(trace) | 320 n = len(trace) |
298 total = calc_total(trace, field) | 321 total = calc_total(trace, field) |
299 max = calc_max(trace, field) | 322 max = calc_max(trace, field) |
300 if n > 0: | 323 if n > 0: |
301 avg = total / n | 324 avg = total / n |
302 else: | 325 else: |
303 avg = 0 | 326 avg = 0 |
304 if n > 1: | 327 if n > 1: |
305 dev = math.sqrt(freduce(lambda t,r: (r - avg) ** 2, field, trace, 0) / | 328 dev = math.sqrt(freduce(lambda t,r: t + (r - avg) ** 2, field, trace, 0) / |
306 (n - 1)) | 329 (n - 1)) |
307 else: | 330 else: |
308 dev = 0 | 331 dev = 0 |
309 | 332 |
310 out.write('<tr><td>%s</td><td>%d</td><td>%d</td>' | 333 out.write('<tr><td>%s</td><td>%d</td><td>%d</td>' |
311 '<td>%d</td><td>%d [dev %f]</td></tr>' % | 334 '<td>%d</td><td>%d [dev %f]</td></tr>' % |
312 (prefix, n, total, max, avg, dev)) | 335 (prefix, n, total, max, avg, dev)) |
313 | 336 |
| 337 def HumanReadable(size): |
| 338 suffixes = ['bytes', 'kB', 'MB', 'GB'] |
| 339 power = 1 |
| 340 for i in range(len(suffixes)): |
| 341 if size < power*1024: |
| 342 return "%.1f" % (float(size) / power) + " " + suffixes[i] |
| 343 power *= 1024 |
| 344 |
| 345 def throughput(name, trace): |
| 346 total_live_after = calc_total(trace, 'total_size_after') |
| 347 total_live_before = calc_total(trace, 'total_size_before') |
| 348 total_gc = calc_total(trace, 'pause') |
| 349 if total_gc == 0: |
| 350 return |
| 351 out.write('GC %s Throughput (after): %s / %s ms = %s/ms<br/>' % |
| 352 (name, |
| 353 HumanReadable(total_live_after), |
| 354 total_gc, |
| 355 HumanReadable(total_live_after / total_gc))) |
| 356 out.write('GC %s Throughput (before): %s / %s ms = %s/ms<br/>' % |
| 357 (name, |
| 358 HumanReadable(total_live_before), |
| 359 total_gc, |
| 360 HumanReadable(total_live_before / total_gc))) |
| 361 |
314 | 362 |
315 with open(filename + '.html', 'w') as out: | 363 with open(filename + '.html', 'w') as out: |
316 out.write('<html><body>') | 364 out.write('<html><body>') |
317 out.write('<table>') | 365 out.write('<table>') |
318 out.write('<tr><td>Phase</td><td>Count</td><td>Time (ms)</td>') | 366 out.write('<tr><td>Phase</td><td>Count</td><td>Time (ms)</td>') |
319 out.write('<td>Max</td><td>Avg</td></tr>') | 367 out.write('<td>Max</td><td>Avg</td></tr>') |
320 stats(out, 'Total in GC', trace, 'pause') | 368 stats(out, 'Total in GC', trace, 'pause') |
321 stats(out, 'Scavenge', scavenges, 'pause') | 369 stats(out, 'Scavenge', scavenges, 'pause') |
322 stats(out, 'MarkSweep', marksweeps, 'pause') | 370 stats(out, 'MarkSweep', marksweeps, 'pause') |
323 stats(out, 'MarkCompact', markcompacts, 'pause') | 371 stats(out, 'MarkCompact', markcompacts, 'pause') |
324 stats(out, 'Mark', filter(lambda r: r['mark'] != 0, trace), 'mark') | 372 stats(out, 'Mark', filter(lambda r: r['mark'] != 0, trace), 'mark') |
325 stats(out, 'Sweep', filter(lambda r: r['sweep'] != 0, trace), 'sweep') | 373 stats(out, 'Sweep', filter(lambda r: r['sweep'] != 0, trace), 'sweep') |
326 stats(out, 'Compact', filter(lambda r: r['compact'] != 0, trace), 'compact') | 374 stats(out, 'Compact', filter(lambda r: r['compact'] != 0, trace), 'compact') |
327 stats(out, | 375 stats(out, |
328 'External', | 376 'External', |
329 filter(lambda r: r['external'] != 0, trace), | 377 filter(lambda r: r['external'] != 0, trace), |
330 'external') | 378 'external') |
331 out.write('</table>') | 379 out.write('</table>') |
| 380 throughput('TOTAL', trace) |
| 381 throughput('MS', marksweeps) |
| 382 throughput('MC', markcompacts) |
| 383 throughput('OLDSPACE', globalgcs) |
| 384 out.write('<br/>') |
332 for chart in charts: | 385 for chart in charts: |
333 out.write('<img src="%s">' % chart) | 386 out.write('<img src="%s">' % chart) |
334 out.write('</body></html>') | 387 out.write('</body></html>') |
335 | 388 |
336 print "%s generated." % (filename + '.html') | 389 print "%s generated." % (filename + '.html') |
337 | 390 |
338 if len(sys.argv) != 2: | 391 if len(sys.argv) != 2: |
339 print "Usage: %s <GC-trace-filename>" % sys.argv[0] | 392 print "Usage: %s <GC-trace-filename>" % sys.argv[0] |
340 sys.exit(1) | 393 sys.exit(1) |
341 | 394 |
342 process_trace(sys.argv[1]) | 395 process_trace(sys.argv[1]) |
OLD | NEW |