[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:
klaasb 2016-07-19 07:17:16 -07:00 committed by Commit bot
parent b401217675
commit a3f598fc85
2 changed files with 63 additions and 32 deletions

View File

@ -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)

View File

@ -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)
])