[interpreter] Add relative numbers to dispatch report
This adds an additional column with percentages to the output of bytecode_dispatch_report.py --top-dispatches-for-bytecode. The percentages always represent the relative number of dispatches to the target bytecode to all dispatches from the source bytecode. The additional flag --sort-sources-relative/-r allows sorting the "Top sources of dispatches to" the given bytecode by this column to more easily find bytecodes that significantly often dispatch to the target. BUG=v8:4899 LOG=N Review-Url: https://codereview.chromium.org/2159683003 Cr-Commit-Position: refs/heads/master@{#37873}
This commit is contained in:
parent
b401217675
commit
a3f598fc85
@ -12,6 +12,7 @@ from matplotlib import colors
|
||||
from matplotlib import pyplot
|
||||
import numpy
|
||||
import struct
|
||||
import sys
|
||||
|
||||
|
||||
__DESCRIPTION = """
|
||||
@ -50,8 +51,8 @@ __COUNTER_MAX = 2**__COUNTER_BITS - 1
|
||||
|
||||
|
||||
def warn_if_counter_may_have_saturated(dispatches_table):
|
||||
for source, counters_from_source in dispatches_table.items():
|
||||
for destination, counter in counters_from_source.items():
|
||||
for source, counters_from_source in iteritems(dispatches_table):
|
||||
for destination, counter in iteritems(counters_from_source):
|
||||
if counter == __COUNTER_MAX:
|
||||
print "WARNING: {} -> {} may have saturated.".format(source,
|
||||
destination)
|
||||
@ -59,8 +60,8 @@ def warn_if_counter_may_have_saturated(dispatches_table):
|
||||
|
||||
def find_top_bytecode_dispatch_pairs(dispatches_table, top_count):
|
||||
def flattened_counters_generator():
|
||||
for source, counters_from_source in dispatches_table.items():
|
||||
for destination, counter in counters_from_source.items():
|
||||
for source, counters_from_source in iteritems(dispatches_table):
|
||||
for destination, counter in iteritems(counters_from_source):
|
||||
yield source, destination, counter
|
||||
|
||||
return heapq.nlargest(top_count, flattened_counters_generator(),
|
||||
@ -77,8 +78,9 @@ def print_top_bytecode_dispatch_pairs(dispatches_table, top_count):
|
||||
|
||||
def find_top_bytecodes(dispatches_table):
|
||||
top_bytecodes = []
|
||||
for bytecode, counters_from_bytecode in dispatches_table.items():
|
||||
top_bytecodes.append((bytecode, sum(counters_from_bytecode.values())))
|
||||
for bytecode, counters_from_bytecode in iteritems(dispatches_table):
|
||||
top_bytecodes.append((bytecode, sum(itervalues(counters_from_bytecode))))
|
||||
|
||||
top_bytecodes.sort(key=lambda x: x[1], reverse=True)
|
||||
return top_bytecodes
|
||||
|
||||
@ -90,30 +92,37 @@ def print_top_bytecodes(dispatches_table):
|
||||
print "{:>12d}\t{}".format(counter, bytecode)
|
||||
|
||||
|
||||
def find_top_dispatch_sources(dispatches_table, destination, top_count):
|
||||
def source_counters_generator():
|
||||
for source, table_row in dispatches_table.items():
|
||||
if destination in table_row:
|
||||
yield source, table_row[destination]
|
||||
def find_top_dispatch_sources_and_destinations(
|
||||
dispatches_table, bytecode, top_count, sort_source_relative):
|
||||
sources = []
|
||||
for source, destinations in iteritems(dispatches_table):
|
||||
total = float(sum(itervalues(destinations)))
|
||||
if bytecode in destinations:
|
||||
count = destinations[bytecode]
|
||||
sources.append((source, count, count / total))
|
||||
|
||||
return heapq.nlargest(top_count, source_counters_generator(),
|
||||
key=lambda x: x[1])
|
||||
destinations = []
|
||||
bytecode_destinations = dispatches_table[bytecode]
|
||||
bytecode_total = float(sum(itervalues(bytecode_destinations)))
|
||||
for destination, count in iteritems(bytecode_destinations):
|
||||
destinations.append((destination, count, count / bytecode_total))
|
||||
|
||||
return (heapq.nlargest(top_count, sources,
|
||||
key=lambda x: x[2 if sort_source_relative else 1]),
|
||||
heapq.nlargest(top_count, destinations, key=lambda x: x[1]))
|
||||
|
||||
|
||||
def print_top_dispatch_sources_and_destinations(dispatches_table, bytecode,
|
||||
top_count):
|
||||
top_sources = find_top_dispatch_sources(dispatches_table, bytecode, top_count)
|
||||
top_destinations = heapq.nlargest(top_count,
|
||||
dispatches_table[bytecode].items(),
|
||||
key=lambda x: x[1])
|
||||
|
||||
top_count, sort_relative):
|
||||
top_sources, top_destinations = find_top_dispatch_sources_and_destinations(
|
||||
dispatches_table, bytecode, top_count, sort_relative)
|
||||
print "Top sources of dispatches to {}:".format(bytecode)
|
||||
for source_name, counter in top_sources:
|
||||
print "{:>12d}\t{}".format(counter, source_name)
|
||||
for source_name, counter, ratio in top_sources:
|
||||
print "{:>12d}\t{:>5.1f}%\t{}".format(counter, ratio * 100, source_name)
|
||||
|
||||
print "\nTop destinations of dispatches from {}:".format(bytecode)
|
||||
for destination_name, counter in top_destinations:
|
||||
print "{:>12d}\t{}".format(counter, destination_name)
|
||||
for destination_name, counter, ratio in top_destinations:
|
||||
print "{:>12d}\t{:>5.1f}%\t{}".format(counter, ratio * 100, destination_name)
|
||||
|
||||
|
||||
def build_counters_matrix(dispatches_table):
|
||||
@ -214,6 +223,12 @@ def parse_command_line():
|
||||
help=("file to save the plot file to. File type is deduced from the "
|
||||
"extension. PDF, SVG, PNG supported")
|
||||
)
|
||||
command_line_parser.add_argument(
|
||||
"--sort-sources-relative", "-r",
|
||||
action="store_true",
|
||||
help=("print top sources in order to how often they dispatch to the "
|
||||
"specified bytecode, only applied when using -f")
|
||||
)
|
||||
command_line_parser.add_argument(
|
||||
"input_filename",
|
||||
metavar="<input filename>",
|
||||
@ -225,6 +240,14 @@ def parse_command_line():
|
||||
return command_line_parser.parse_args()
|
||||
|
||||
|
||||
def itervalues(d):
|
||||
return d.values() if sys.version_info[0] > 2 else d.itervalues()
|
||||
|
||||
|
||||
def iteritems(d):
|
||||
return d.items() if sys.version_info[0] > 2 else d.iteritems()
|
||||
|
||||
|
||||
def main():
|
||||
program_options = parse_command_line()
|
||||
|
||||
@ -249,7 +272,7 @@ def main():
|
||||
elif program_options.top_dispatches_for_bytecode:
|
||||
print_top_dispatch_sources_and_destinations(
|
||||
dispatches_table, program_options.top_dispatches_for_bytecode,
|
||||
program_options.top_entries_count)
|
||||
program_options.top_entries_count, program_options.sort_sources_relative)
|
||||
else:
|
||||
print_top_bytecodes(dispatches_table)
|
||||
|
||||
|
@ -42,13 +42,21 @@ class BytecodeDispatchesReportTest(unittest.TestCase):
|
||||
('b', 5)
|
||||
])
|
||||
|
||||
def test_find_top_dispatch_sources(self):
|
||||
top_dispatch_sources = bdr.find_top_dispatch_sources({
|
||||
"a": {"a": 10, "b": 8, "c": 7},
|
||||
def test_find_top_dispatch_sources_and_destinations(self):
|
||||
d = {
|
||||
"a": {"a": 4, "b": 2, "c": 4},
|
||||
"b": {"a": 1, "c": 4},
|
||||
"c": {"a": 42, "b": 12, "c": 99}
|
||||
}, "b", 10)
|
||||
self.assertListEqual(top_dispatch_sources, [
|
||||
("c", 12),
|
||||
("a", 8)
|
||||
"c": {"a": 40, "b": 10, "c": 50}
|
||||
}
|
||||
top_sources, top_dests = bdr.find_top_dispatch_sources_and_destinations(
|
||||
d, "b", 10, False)
|
||||
self.assertListEqual(top_sources, [
|
||||
("c", 10, 0.1),
|
||||
("a", 2, 0.2)
|
||||
])
|
||||
top_sources, top_dests = bdr.find_top_dispatch_sources_and_destinations(
|
||||
d, "b", 10, True)
|
||||
self.assertListEqual(top_sources, [
|
||||
("a", 2, 0.2),
|
||||
("c", 10, 0.1)
|
||||
])
|
||||
|
Loading…
Reference in New Issue
Block a user