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 |