11cb0ef41Sopenharmony_ci#!/usr/bin/env python 21cb0ef41Sopenharmony_ci# 31cb0ef41Sopenharmony_ci# Copyright 2010 the V8 project authors. All rights reserved. 41cb0ef41Sopenharmony_ci# Redistribution and use in source and binary forms, with or without 51cb0ef41Sopenharmony_ci# modification, are permitted provided that the following conditions are 61cb0ef41Sopenharmony_ci# met: 71cb0ef41Sopenharmony_ci# 81cb0ef41Sopenharmony_ci# * Redistributions of source code must retain the above copyright 91cb0ef41Sopenharmony_ci# notice, this list of conditions and the following disclaimer. 101cb0ef41Sopenharmony_ci# * Redistributions in binary form must reproduce the above 111cb0ef41Sopenharmony_ci# copyright notice, this list of conditions and the following 121cb0ef41Sopenharmony_ci# disclaimer in the documentation and/or other materials provided 131cb0ef41Sopenharmony_ci# with the distribution. 141cb0ef41Sopenharmony_ci# * Neither the name of Google Inc. nor the names of its 151cb0ef41Sopenharmony_ci# contributors may be used to endorse or promote products derived 161cb0ef41Sopenharmony_ci# from this software without specific prior written permission. 171cb0ef41Sopenharmony_ci# 181cb0ef41Sopenharmony_ci# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 191cb0ef41Sopenharmony_ci# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 201cb0ef41Sopenharmony_ci# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 211cb0ef41Sopenharmony_ci# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 221cb0ef41Sopenharmony_ci# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 231cb0ef41Sopenharmony_ci# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 241cb0ef41Sopenharmony_ci# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 251cb0ef41Sopenharmony_ci# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 261cb0ef41Sopenharmony_ci# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 271cb0ef41Sopenharmony_ci# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 281cb0ef41Sopenharmony_ci# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 291cb0ef41Sopenharmony_ci# 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_ci# 321cb0ef41Sopenharmony_ci# This is an utility for plotting charts based on GC traces produced by V8 when 331cb0ef41Sopenharmony_ci# run with flags --trace-gc --trace-gc-nvp. Relies on gnuplot for actual 341cb0ef41Sopenharmony_ci# plotting. 351cb0ef41Sopenharmony_ci# 361cb0ef41Sopenharmony_ci# Usage: gc-nvp-trace-processor.py <GC-trace-filename> 371cb0ef41Sopenharmony_ci# 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_ci 401cb0ef41Sopenharmony_ci# for py2/py3 compatibility 411cb0ef41Sopenharmony_cifrom __future__ import with_statement 421cb0ef41Sopenharmony_cifrom __future__ import print_function 431cb0ef41Sopenharmony_cifrom functools import reduce 441cb0ef41Sopenharmony_ci 451cb0ef41Sopenharmony_ciimport sys, types, subprocess, math 461cb0ef41Sopenharmony_ciimport gc_nvp_common 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_ci 491cb0ef41Sopenharmony_citry: 501cb0ef41Sopenharmony_ci long # Python 2 511cb0ef41Sopenharmony_ciexcept NameError: 521cb0ef41Sopenharmony_ci long = int # Python 3 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_ci 551cb0ef41Sopenharmony_cidef flatten(l): 561cb0ef41Sopenharmony_ci flat = [] 571cb0ef41Sopenharmony_ci for i in l: flat.extend(i) 581cb0ef41Sopenharmony_ci return flat 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_cidef gnuplot(script): 611cb0ef41Sopenharmony_ci gnuplot = subprocess.Popen(["gnuplot"], stdin=subprocess.PIPE) 621cb0ef41Sopenharmony_ci gnuplot.stdin.write(script) 631cb0ef41Sopenharmony_ci gnuplot.stdin.close() 641cb0ef41Sopenharmony_ci gnuplot.wait() 651cb0ef41Sopenharmony_ci 661cb0ef41Sopenharmony_cix1y1 = 'x1y1' 671cb0ef41Sopenharmony_cix1y2 = 'x1y2' 681cb0ef41Sopenharmony_cix2y1 = 'x2y1' 691cb0ef41Sopenharmony_cix2y2 = 'x2y2' 701cb0ef41Sopenharmony_ci 711cb0ef41Sopenharmony_ciclass Item(object): 721cb0ef41Sopenharmony_ci def __init__(self, title, field, axis = x1y1, **keywords): 731cb0ef41Sopenharmony_ci self.title = title 741cb0ef41Sopenharmony_ci self.axis = axis 751cb0ef41Sopenharmony_ci self.props = keywords 761cb0ef41Sopenharmony_ci if type(field) is list: 771cb0ef41Sopenharmony_ci self.field = field 781cb0ef41Sopenharmony_ci else: 791cb0ef41Sopenharmony_ci self.field = [field] 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_ci def fieldrefs(self): 821cb0ef41Sopenharmony_ci return self.field 831cb0ef41Sopenharmony_ci 841cb0ef41Sopenharmony_ci def to_gnuplot(self, context): 851cb0ef41Sopenharmony_ci args = ['"%s"' % context.datafile, 861cb0ef41Sopenharmony_ci 'using %s' % context.format_fieldref(self.field), 871cb0ef41Sopenharmony_ci 'title "%s"' % self.title, 881cb0ef41Sopenharmony_ci 'axis %s' % self.axis] 891cb0ef41Sopenharmony_ci if 'style' in self.props: 901cb0ef41Sopenharmony_ci args.append('with %s' % self.props['style']) 911cb0ef41Sopenharmony_ci if 'lc' in self.props: 921cb0ef41Sopenharmony_ci args.append('lc rgb "%s"' % self.props['lc']) 931cb0ef41Sopenharmony_ci if 'fs' in self.props: 941cb0ef41Sopenharmony_ci args.append('fs %s' % self.props['fs']) 951cb0ef41Sopenharmony_ci return ' '.join(args) 961cb0ef41Sopenharmony_ci 971cb0ef41Sopenharmony_ciclass Plot(object): 981cb0ef41Sopenharmony_ci def __init__(self, *items): 991cb0ef41Sopenharmony_ci self.items = items 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_ci def fieldrefs(self): 1021cb0ef41Sopenharmony_ci return flatten([item.fieldrefs() for item in self.items]) 1031cb0ef41Sopenharmony_ci 1041cb0ef41Sopenharmony_ci def to_gnuplot(self, ctx): 1051cb0ef41Sopenharmony_ci return 'plot ' + ', '.join([item.to_gnuplot(ctx) for item in self.items]) 1061cb0ef41Sopenharmony_ci 1071cb0ef41Sopenharmony_ciclass Set(object): 1081cb0ef41Sopenharmony_ci def __init__(self, value): 1091cb0ef41Sopenharmony_ci self.value = value 1101cb0ef41Sopenharmony_ci 1111cb0ef41Sopenharmony_ci def to_gnuplot(self, ctx): 1121cb0ef41Sopenharmony_ci return 'set ' + self.value 1131cb0ef41Sopenharmony_ci 1141cb0ef41Sopenharmony_ci def fieldrefs(self): 1151cb0ef41Sopenharmony_ci return [] 1161cb0ef41Sopenharmony_ci 1171cb0ef41Sopenharmony_ciclass Context(object): 1181cb0ef41Sopenharmony_ci def __init__(self, datafile, field_to_index): 1191cb0ef41Sopenharmony_ci self.datafile = datafile 1201cb0ef41Sopenharmony_ci self.field_to_index = field_to_index 1211cb0ef41Sopenharmony_ci 1221cb0ef41Sopenharmony_ci def format_fieldref(self, fieldref): 1231cb0ef41Sopenharmony_ci return ':'.join([str(self.field_to_index[field]) for field in fieldref]) 1241cb0ef41Sopenharmony_ci 1251cb0ef41Sopenharmony_cidef collect_fields(plot): 1261cb0ef41Sopenharmony_ci field_to_index = {} 1271cb0ef41Sopenharmony_ci fields = [] 1281cb0ef41Sopenharmony_ci 1291cb0ef41Sopenharmony_ci def add_field(field): 1301cb0ef41Sopenharmony_ci if field not in field_to_index: 1311cb0ef41Sopenharmony_ci fields.append(field) 1321cb0ef41Sopenharmony_ci field_to_index[field] = len(fields) 1331cb0ef41Sopenharmony_ci 1341cb0ef41Sopenharmony_ci for field in flatten([item.fieldrefs() for item in plot]): 1351cb0ef41Sopenharmony_ci add_field(field) 1361cb0ef41Sopenharmony_ci 1371cb0ef41Sopenharmony_ci return (fields, field_to_index) 1381cb0ef41Sopenharmony_ci 1391cb0ef41Sopenharmony_cidef is_y2_used(plot): 1401cb0ef41Sopenharmony_ci for subplot in plot: 1411cb0ef41Sopenharmony_ci if isinstance(subplot, Plot): 1421cb0ef41Sopenharmony_ci for item in subplot.items: 1431cb0ef41Sopenharmony_ci if item.axis == x1y2 or item.axis == x2y2: 1441cb0ef41Sopenharmony_ci return True 1451cb0ef41Sopenharmony_ci return False 1461cb0ef41Sopenharmony_ci 1471cb0ef41Sopenharmony_cidef get_field(trace_line, field): 1481cb0ef41Sopenharmony_ci t = type(field) 1491cb0ef41Sopenharmony_ci if t is bytes: 1501cb0ef41Sopenharmony_ci return trace_line[field] 1511cb0ef41Sopenharmony_ci elif t is types.FunctionType: 1521cb0ef41Sopenharmony_ci return field(trace_line) 1531cb0ef41Sopenharmony_ci 1541cb0ef41Sopenharmony_cidef generate_datafile(datafile_name, trace, fields): 1551cb0ef41Sopenharmony_ci with open(datafile_name, 'w') as datafile: 1561cb0ef41Sopenharmony_ci for line in trace: 1571cb0ef41Sopenharmony_ci data_line = [str(get_field(line, field)) for field in fields] 1581cb0ef41Sopenharmony_ci datafile.write('\t'.join(data_line)) 1591cb0ef41Sopenharmony_ci datafile.write('\n') 1601cb0ef41Sopenharmony_ci 1611cb0ef41Sopenharmony_cidef generate_script_and_datafile(plot, trace, datafile, output): 1621cb0ef41Sopenharmony_ci (fields, field_to_index) = collect_fields(plot) 1631cb0ef41Sopenharmony_ci generate_datafile(datafile, trace, fields) 1641cb0ef41Sopenharmony_ci script = [ 1651cb0ef41Sopenharmony_ci 'set terminal png', 1661cb0ef41Sopenharmony_ci 'set output "%s"' % output, 1671cb0ef41Sopenharmony_ci 'set autoscale', 1681cb0ef41Sopenharmony_ci 'set ytics nomirror', 1691cb0ef41Sopenharmony_ci 'set xtics nomirror', 1701cb0ef41Sopenharmony_ci 'set key below' 1711cb0ef41Sopenharmony_ci ] 1721cb0ef41Sopenharmony_ci 1731cb0ef41Sopenharmony_ci if is_y2_used(plot): 1741cb0ef41Sopenharmony_ci script.append('set autoscale y2') 1751cb0ef41Sopenharmony_ci script.append('set y2tics') 1761cb0ef41Sopenharmony_ci 1771cb0ef41Sopenharmony_ci context = Context(datafile, field_to_index) 1781cb0ef41Sopenharmony_ci 1791cb0ef41Sopenharmony_ci for item in plot: 1801cb0ef41Sopenharmony_ci script.append(item.to_gnuplot(context)) 1811cb0ef41Sopenharmony_ci 1821cb0ef41Sopenharmony_ci return '\n'.join(script) 1831cb0ef41Sopenharmony_ci 1841cb0ef41Sopenharmony_cidef plot_all(plots, trace, prefix): 1851cb0ef41Sopenharmony_ci charts = [] 1861cb0ef41Sopenharmony_ci 1871cb0ef41Sopenharmony_ci for plot in plots: 1881cb0ef41Sopenharmony_ci outfilename = "%s_%d.png" % (prefix, len(charts)) 1891cb0ef41Sopenharmony_ci charts.append(outfilename) 1901cb0ef41Sopenharmony_ci script = generate_script_and_datafile(plot, trace, '~datafile', outfilename) 1911cb0ef41Sopenharmony_ci print('Plotting %s...' % outfilename) 1921cb0ef41Sopenharmony_ci gnuplot(script) 1931cb0ef41Sopenharmony_ci 1941cb0ef41Sopenharmony_ci return charts 1951cb0ef41Sopenharmony_ci 1961cb0ef41Sopenharmony_cidef reclaimed_bytes(row): 1971cb0ef41Sopenharmony_ci return row['total_size_before'] - row['total_size_after'] 1981cb0ef41Sopenharmony_ci 1991cb0ef41Sopenharmony_cidef other_scope(r): 2001cb0ef41Sopenharmony_ci if r['gc'] == 's': 2011cb0ef41Sopenharmony_ci # there is no 'other' scope for scavenging collections. 2021cb0ef41Sopenharmony_ci return 0 2031cb0ef41Sopenharmony_ci return r['pause'] - r['mark'] - r['sweep'] - r['external'] 2041cb0ef41Sopenharmony_ci 2051cb0ef41Sopenharmony_cidef scavenge_scope(r): 2061cb0ef41Sopenharmony_ci if r['gc'] == 's': 2071cb0ef41Sopenharmony_ci return r['pause'] - r['external'] 2081cb0ef41Sopenharmony_ci return 0 2091cb0ef41Sopenharmony_ci 2101cb0ef41Sopenharmony_ci 2111cb0ef41Sopenharmony_cidef real_mutator(r): 2121cb0ef41Sopenharmony_ci return r['mutator'] - r['steps_took'] 2131cb0ef41Sopenharmony_ci 2141cb0ef41Sopenharmony_ciplots = [ 2151cb0ef41Sopenharmony_ci [ 2161cb0ef41Sopenharmony_ci Set('style fill solid 0.5 noborder'), 2171cb0ef41Sopenharmony_ci Set('style histogram rowstacked'), 2181cb0ef41Sopenharmony_ci Set('style data histograms'), 2191cb0ef41Sopenharmony_ci Plot(Item('Scavenge', scavenge_scope, lc = 'green'), 2201cb0ef41Sopenharmony_ci Item('Marking', 'mark', lc = 'purple'), 2211cb0ef41Sopenharmony_ci Item('Sweep', 'sweep', lc = 'blue'), 2221cb0ef41Sopenharmony_ci Item('External', 'external', lc = '#489D43'), 2231cb0ef41Sopenharmony_ci Item('Other', other_scope, lc = 'grey'), 2241cb0ef41Sopenharmony_ci Item('IGC Steps', 'steps_took', lc = '#FF6347')) 2251cb0ef41Sopenharmony_ci ], 2261cb0ef41Sopenharmony_ci [ 2271cb0ef41Sopenharmony_ci Set('style fill solid 0.5 noborder'), 2281cb0ef41Sopenharmony_ci Set('style histogram rowstacked'), 2291cb0ef41Sopenharmony_ci Set('style data histograms'), 2301cb0ef41Sopenharmony_ci Plot(Item('Scavenge', scavenge_scope, lc = 'green'), 2311cb0ef41Sopenharmony_ci Item('Marking', 'mark', lc = 'purple'), 2321cb0ef41Sopenharmony_ci Item('Sweep', 'sweep', lc = 'blue'), 2331cb0ef41Sopenharmony_ci Item('External', 'external', lc = '#489D43'), 2341cb0ef41Sopenharmony_ci Item('Other', other_scope, lc = '#ADD8E6'), 2351cb0ef41Sopenharmony_ci Item('External', 'external', lc = '#D3D3D3')) 2361cb0ef41Sopenharmony_ci ], 2371cb0ef41Sopenharmony_ci 2381cb0ef41Sopenharmony_ci [ 2391cb0ef41Sopenharmony_ci Plot(Item('Mutator', real_mutator, lc = 'black', style = 'lines')) 2401cb0ef41Sopenharmony_ci ], 2411cb0ef41Sopenharmony_ci [ 2421cb0ef41Sopenharmony_ci Set('style histogram rowstacked'), 2431cb0ef41Sopenharmony_ci Set('style data histograms'), 2441cb0ef41Sopenharmony_ci Plot(Item('Heap Size (before GC)', 'total_size_before', x1y2, 2451cb0ef41Sopenharmony_ci fs = 'solid 0.4 noborder', 2461cb0ef41Sopenharmony_ci lc = 'green'), 2471cb0ef41Sopenharmony_ci Item('Total holes (after GC)', 'holes_size_before', x1y2, 2481cb0ef41Sopenharmony_ci fs = 'solid 0.4 noborder', 2491cb0ef41Sopenharmony_ci lc = 'red'), 2501cb0ef41Sopenharmony_ci Item('GC Time', ['i', 'pause'], style = 'lines', lc = 'red')) 2511cb0ef41Sopenharmony_ci ], 2521cb0ef41Sopenharmony_ci [ 2531cb0ef41Sopenharmony_ci Set('style histogram rowstacked'), 2541cb0ef41Sopenharmony_ci Set('style data histograms'), 2551cb0ef41Sopenharmony_ci Plot(Item('Heap Size (after GC)', 'total_size_after', x1y2, 2561cb0ef41Sopenharmony_ci fs = 'solid 0.4 noborder', 2571cb0ef41Sopenharmony_ci lc = 'green'), 2581cb0ef41Sopenharmony_ci Item('Total holes (after GC)', 'holes_size_after', x1y2, 2591cb0ef41Sopenharmony_ci fs = 'solid 0.4 noborder', 2601cb0ef41Sopenharmony_ci lc = 'red'), 2611cb0ef41Sopenharmony_ci Item('GC Time', ['i', 'pause'], 2621cb0ef41Sopenharmony_ci style = 'lines', 2631cb0ef41Sopenharmony_ci lc = 'red')) 2641cb0ef41Sopenharmony_ci ], 2651cb0ef41Sopenharmony_ci [ 2661cb0ef41Sopenharmony_ci Set('style fill solid 0.5 noborder'), 2671cb0ef41Sopenharmony_ci Set('style data histograms'), 2681cb0ef41Sopenharmony_ci Plot(Item('Allocated', 'allocated'), 2691cb0ef41Sopenharmony_ci Item('Reclaimed', reclaimed_bytes), 2701cb0ef41Sopenharmony_ci Item('Promoted', 'promoted', style = 'lines', lc = 'black')) 2711cb0ef41Sopenharmony_ci ], 2721cb0ef41Sopenharmony_ci] 2731cb0ef41Sopenharmony_ci 2741cb0ef41Sopenharmony_cidef freduce(f, field, trace, init): 2751cb0ef41Sopenharmony_ci return reduce(lambda t,r: f(t, r[field]), trace, init) 2761cb0ef41Sopenharmony_ci 2771cb0ef41Sopenharmony_cidef calc_total(trace, field): 2781cb0ef41Sopenharmony_ci return freduce(lambda t,v: t + long(v), field, trace, long(0)) 2791cb0ef41Sopenharmony_ci 2801cb0ef41Sopenharmony_cidef calc_max(trace, field): 2811cb0ef41Sopenharmony_ci return freduce(lambda t,r: max(t, r), field, trace, 0) 2821cb0ef41Sopenharmony_ci 2831cb0ef41Sopenharmony_cidef count_nonzero(trace, field): 2841cb0ef41Sopenharmony_ci return freduce(lambda t,r: t if r == 0 else t + 1, field, trace, 0) 2851cb0ef41Sopenharmony_ci 2861cb0ef41Sopenharmony_ci 2871cb0ef41Sopenharmony_cidef process_trace(filename): 2881cb0ef41Sopenharmony_ci trace = gc_nvp_common.parse_gc_trace(filename) 2891cb0ef41Sopenharmony_ci 2901cb0ef41Sopenharmony_ci marksweeps = filter(lambda r: r['gc'] == 'ms', trace) 2911cb0ef41Sopenharmony_ci scavenges = filter(lambda r: r['gc'] == 's', trace) 2921cb0ef41Sopenharmony_ci globalgcs = filter(lambda r: r['gc'] != 's', trace) 2931cb0ef41Sopenharmony_ci 2941cb0ef41Sopenharmony_ci 2951cb0ef41Sopenharmony_ci charts = plot_all(plots, trace, filename) 2961cb0ef41Sopenharmony_ci 2971cb0ef41Sopenharmony_ci def stats(out, prefix, trace, field): 2981cb0ef41Sopenharmony_ci n = len(trace) 2991cb0ef41Sopenharmony_ci total = calc_total(trace, field) 3001cb0ef41Sopenharmony_ci max = calc_max(trace, field) 3011cb0ef41Sopenharmony_ci if n > 0: 3021cb0ef41Sopenharmony_ci avg = total / n 3031cb0ef41Sopenharmony_ci else: 3041cb0ef41Sopenharmony_ci avg = 0 3051cb0ef41Sopenharmony_ci if n > 1: 3061cb0ef41Sopenharmony_ci dev = math.sqrt(freduce(lambda t,r: t + (r - avg) ** 2, field, trace, 0) / 3071cb0ef41Sopenharmony_ci (n - 1)) 3081cb0ef41Sopenharmony_ci else: 3091cb0ef41Sopenharmony_ci dev = 0 3101cb0ef41Sopenharmony_ci 3111cb0ef41Sopenharmony_ci out.write('<tr><td>%s</td><td>%d</td><td>%d</td>' 3121cb0ef41Sopenharmony_ci '<td>%d</td><td>%d [dev %f]</td></tr>' % 3131cb0ef41Sopenharmony_ci (prefix, n, total, max, avg, dev)) 3141cb0ef41Sopenharmony_ci 3151cb0ef41Sopenharmony_ci def HumanReadable(size): 3161cb0ef41Sopenharmony_ci suffixes = ['bytes', 'kB', 'MB', 'GB'] 3171cb0ef41Sopenharmony_ci power = 1 3181cb0ef41Sopenharmony_ci for i in range(len(suffixes)): 3191cb0ef41Sopenharmony_ci if size < power*1024: 3201cb0ef41Sopenharmony_ci return "%.1f" % (float(size) / power) + " " + suffixes[i] 3211cb0ef41Sopenharmony_ci power *= 1024 3221cb0ef41Sopenharmony_ci 3231cb0ef41Sopenharmony_ci def throughput(name, trace): 3241cb0ef41Sopenharmony_ci total_live_after = calc_total(trace, 'total_size_after') 3251cb0ef41Sopenharmony_ci total_live_before = calc_total(trace, 'total_size_before') 3261cb0ef41Sopenharmony_ci total_gc = calc_total(trace, 'pause') 3271cb0ef41Sopenharmony_ci if total_gc == 0: 3281cb0ef41Sopenharmony_ci return 3291cb0ef41Sopenharmony_ci out.write('GC %s Throughput (after): %s / %s ms = %s/ms<br/>' % 3301cb0ef41Sopenharmony_ci (name, 3311cb0ef41Sopenharmony_ci HumanReadable(total_live_after), 3321cb0ef41Sopenharmony_ci total_gc, 3331cb0ef41Sopenharmony_ci HumanReadable(total_live_after / total_gc))) 3341cb0ef41Sopenharmony_ci out.write('GC %s Throughput (before): %s / %s ms = %s/ms<br/>' % 3351cb0ef41Sopenharmony_ci (name, 3361cb0ef41Sopenharmony_ci HumanReadable(total_live_before), 3371cb0ef41Sopenharmony_ci total_gc, 3381cb0ef41Sopenharmony_ci HumanReadable(total_live_before / total_gc))) 3391cb0ef41Sopenharmony_ci 3401cb0ef41Sopenharmony_ci 3411cb0ef41Sopenharmony_ci with open(filename + '.html', 'w') as out: 3421cb0ef41Sopenharmony_ci out.write('<html><body>') 3431cb0ef41Sopenharmony_ci out.write('<table>') 3441cb0ef41Sopenharmony_ci out.write('<tr><td>Phase</td><td>Count</td><td>Time (ms)</td>') 3451cb0ef41Sopenharmony_ci out.write('<td>Max</td><td>Avg</td></tr>') 3461cb0ef41Sopenharmony_ci stats(out, 'Total in GC', trace, 'pause') 3471cb0ef41Sopenharmony_ci stats(out, 'Scavenge', scavenges, 'pause') 3481cb0ef41Sopenharmony_ci stats(out, 'MarkSweep', marksweeps, 'pause') 3491cb0ef41Sopenharmony_ci stats(out, 'Mark', filter(lambda r: r['mark'] != 0, trace), 'mark') 3501cb0ef41Sopenharmony_ci stats(out, 'Sweep', filter(lambda r: r['sweep'] != 0, trace), 'sweep') 3511cb0ef41Sopenharmony_ci stats(out, 3521cb0ef41Sopenharmony_ci 'External', 3531cb0ef41Sopenharmony_ci filter(lambda r: r['external'] != 0, trace), 3541cb0ef41Sopenharmony_ci 'external') 3551cb0ef41Sopenharmony_ci out.write('</table>') 3561cb0ef41Sopenharmony_ci throughput('TOTAL', trace) 3571cb0ef41Sopenharmony_ci throughput('MS', marksweeps) 3581cb0ef41Sopenharmony_ci throughput('OLDSPACE', globalgcs) 3591cb0ef41Sopenharmony_ci out.write('<br/>') 3601cb0ef41Sopenharmony_ci for chart in charts: 3611cb0ef41Sopenharmony_ci out.write('<img src="%s">' % chart) 3621cb0ef41Sopenharmony_ci out.write('</body></html>') 3631cb0ef41Sopenharmony_ci 3641cb0ef41Sopenharmony_ci print("%s generated." % (filename + '.html')) 3651cb0ef41Sopenharmony_ci 3661cb0ef41Sopenharmony_ciif len(sys.argv) != 2: 3671cb0ef41Sopenharmony_ci print("Usage: %s <GC-trace-filename>" % sys.argv[0]) 3681cb0ef41Sopenharmony_ci sys.exit(1) 3691cb0ef41Sopenharmony_ci 3701cb0ef41Sopenharmony_ciprocess_trace(sys.argv[1]) 371