Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 #! /usr/bin/python | |
| 2 # | |
| 3 # Copyright 2016 the V8 project authors. All rights reserved. | |
| 4 # Use of this source code is governed by a BSD-style license that can be | |
| 5 # found in the LICENSE file. | |
| 6 # | |
| 7 | |
| 8 import argparse | |
| 9 import heapq | |
| 10 import json | |
| 11 from matplotlib import colors | |
| 12 from matplotlib import pyplot | |
| 13 import numpy | |
| 14 import struct | |
| 15 | |
| 16 | |
| 17 __DESCRIPTION = """ | |
| 18 Process v8.ignition_dispatches_counters.json and list top counters, | |
| 19 or plot a dispatch heatmap. | |
| 20 """ | |
| 21 | |
| 22 | |
| 23 __HELP_EPILOGUE = """ | |
| 24 examples: | |
| 25 # Print the top 10 counters (default mode), reading from default | |
| 26 # filename v8.ignition_dispatches_counters.json | |
| 27 $ tools/ignition/bytecode_dispatches_report.py | |
| 28 | |
| 29 # Print the top 15 counters reading from data.json | |
| 30 $ tools/ignition/bytecode_dispatches_report.py -t 15 data.json | |
| 31 | |
| 32 # Do not print the top counters and save to default filename | |
| 33 # v8.ignition_dispatches_counters.svg | |
| 34 $ tools/ignition/bytecode_dispatches_report.py -t 0 -p -o data.svg | |
|
rmcilroy
2016/04/12 14:08:51
Please update this example if you take the comment
Stefano Sanfilippo
2016/04/12 14:26:26
Done.
| |
| 35 | |
| 36 # Print the top 10 counters and save a heatmap to data.svg | |
| 37 $ tools/ignition/bytecode_dispatches_report.py -p -o data.svg | |
| 38 | |
| 39 # Open the heatmap in an interactive viewer | |
| 40 $ tools/ignition/bytecode_dispatches_report.py -p -i | |
| 41 """ | |
| 42 | |
| 43 __COUNTER_BITS = struct.calcsize("P") * 8 # Size in bits of a pointer | |
| 44 | |
| 45 | |
| 46 __COUNTER_MAX = 2**__COUNTER_BITS - 1 | |
|
rmcilroy
2016/04/12 14:08:51
nit - remove newlines between __COUNTER_BITS and _
Stefano Sanfilippo
2016/04/12 14:26:26
Done.
| |
| 47 | |
| 48 | |
| 49 def warn_if_counter_may_have_saturated(dispatches_table): | |
| 50 for source, counters_from_source in dispatches_table.items(): | |
| 51 for destination, counter in counters_from_source.items(): | |
| 52 if counter == __COUNTER_MAX: | |
| 53 print "WARNING: {} -> {} may have saturated.".format(source, | |
| 54 destination) | |
| 55 | |
| 56 | |
| 57 def print_top_counters(dispatches_table, top_number): | |
| 58 flattened_counters = {} | |
| 59 for source, counters_from_source in dispatches_table.items(): | |
| 60 for destination, counter in counters_from_source.items(): | |
| 61 flattened_counters[source, destination] = counter | |
| 62 | |
| 63 top_counters = heapq.nlargest(top_number, flattened_counters.items(), | |
| 64 key=lambda x: x[1]) | |
| 65 | |
| 66 print "Top {} dispatch counters:".format(top_number) | |
| 67 for source_destination_pair, counter in top_counters: | |
| 68 print "{:>12d}\t{}".format(counter, " -> ".join(source_destination_pair)) | |
| 69 | |
| 70 | |
| 71 def plot_dispatches_table(dispatches_table, figure, axis): | |
| 72 labels = sorted(dispatches_table.keys()) | |
| 73 | |
| 74 counters_matrix = numpy.empty([len(labels), len(labels)], dtype=int) | |
| 75 for from_index, from_name in enumerate(labels): | |
| 76 current_row = dispatches_table[from_name]; | |
| 77 for to_index, to_name in enumerate(labels): | |
| 78 counters_matrix[from_index, to_index] = current_row.get(to_name, 0) | |
| 79 | |
| 80 # Reverse y axis for a nicer appeareance | |
|
rmcilroy
2016/04/12 14:08:51
appearance
Stefano Sanfilippo
2016/04/12 14:26:26
Done.
| |
| 81 xlabels = labels | |
| 82 ylabels = list(reversed(xlabels)) | |
| 83 counters_matrix = numpy.flipud(counters_matrix) | |
| 84 | |
| 85 image = axis.pcolor( | |
| 86 counters_matrix, | |
| 87 cmap='jet', | |
| 88 norm=colors.LogNorm(), | |
| 89 edgecolor='grey', | |
| 90 linestyle='dotted', | |
| 91 linewidth=0.5 | |
| 92 ) | |
| 93 | |
| 94 axis.xaxis.set( | |
| 95 ticks=numpy.arange(0.5, len(xlabels)), | |
| 96 label="From bytecode handler" | |
| 97 ) | |
| 98 axis.xaxis.tick_top() | |
| 99 axis.set_xlim(0, len(xlabels)) | |
| 100 axis.set_xticklabels(xlabels, rotation='vertical') | |
| 101 | |
| 102 axis.yaxis.set( | |
| 103 ticks=numpy.arange(0.5, len(ylabels)), | |
| 104 label="To bytecode handler", | |
| 105 ticklabels=ylabels | |
| 106 ) | |
| 107 axis.set_ylim(0, len(ylabels)) | |
| 108 | |
| 109 figure.colorbar( | |
| 110 image, | |
| 111 ax=axis, | |
| 112 fraction=0.01, | |
| 113 pad=0.01 | |
| 114 ) | |
| 115 | |
| 116 | |
| 117 def parse_command_line(): | |
| 118 command_line_parser = argparse.ArgumentParser( | |
| 119 formatter_class=argparse.RawDescriptionHelpFormatter, | |
| 120 description=__DESCRIPTION, | |
| 121 epilog=__HELP_EPILOGUE | |
| 122 ) | |
| 123 command_line_parser.add_argument( | |
| 124 "--plot_size", "-s", | |
| 125 metavar="N", | |
| 126 default=30, | |
| 127 help="shorter side, in inches, of the output plot (default 30)" | |
| 128 ) | |
| 129 command_line_parser.add_argument( | |
| 130 "--plot", "-p", | |
| 131 action="store_true", | |
| 132 help="plot dispatches table heatmap" | |
| 133 ) | |
| 134 command_line_parser.add_argument( | |
| 135 "--interactive", "-i", | |
| 136 action="store_true", | |
| 137 help="open an interactive viewer, rather than writing to file" | |
| 138 ) | |
| 139 command_line_parser.add_argument( | |
| 140 "--print_top", "-t", | |
|
rmcilroy
2016/04/12 14:08:51
name "top_count"
Stefano Sanfilippo
2016/04/12 14:26:26
Done.
| |
| 141 metavar="N", | |
| 142 type=int, | |
| 143 default=10, | |
| 144 help="print the top N counters (default 10)" | |
| 145 ) | |
| 146 command_line_parser.add_argument( | |
| 147 "--output_filename", "-o", | |
| 148 metavar="<output filename>", | |
| 149 default="v8.ignition_dispatches_table.svg", | |
| 150 help=("file to save the plot file to. File type is deduced from the " | |
| 151 "extension. PDF, SVG, PNG supported") | |
| 152 ) | |
| 153 command_line_parser.add_argument( | |
| 154 "input_filename", | |
| 155 metavar="<input filename>", | |
| 156 default="v8.ignition_dispatches_table.json", | |
| 157 nargs='?', | |
| 158 help="Ignition counters JSON file" | |
| 159 ) | |
| 160 | |
| 161 return command_line_parser.parse_args() | |
| 162 | |
| 163 | |
| 164 def main(): | |
| 165 program_options = parse_command_line() | |
| 166 | |
| 167 with open(program_options.input_filename) as stream: | |
| 168 dispatches_table = json.load(stream) | |
| 169 | |
| 170 warn_if_counter_may_have_saturated(dispatches_table) | |
| 171 | |
| 172 if program_options.print_top > 0: | |
|
rmcilroy
2016/04/12 14:08:51
This is default 10, so the only way to avoid it is
Stefano Sanfilippo
2016/04/12 14:26:26
Done.
| |
| 173 print_top_counters(dispatches_table, program_options.print_top) | |
| 174 | |
| 175 if program_options.plot: | |
| 176 figure, axis = pyplot.subplots() | |
| 177 plot_dispatches_table(dispatches_table, figure, axis) | |
| 178 | |
| 179 if program_options.interactive: | |
| 180 pyplot.show() | |
| 181 else: | |
| 182 figure.set_size_inches(program_options.plot_size, | |
| 183 program_options.plot_size) | |
| 184 pyplot.savefig(program_options.output_filename) | |
| 185 | |
| 186 | |
| 187 if __name__ == "__main__": | |
| 188 main() | |
| OLD | NEW |