Commit a3f598fc authored by klaasb's avatar klaasb Committed by Commit bot

[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}
parent b4012176
...@@ -12,6 +12,7 @@ from matplotlib import colors ...@@ -12,6 +12,7 @@ from matplotlib import colors
from matplotlib import pyplot from matplotlib import pyplot
import numpy import numpy
import struct import struct
import sys
__DESCRIPTION = """ __DESCRIPTION = """
...@@ -50,8 +51,8 @@ __COUNTER_MAX = 2**__COUNTER_BITS - 1 ...@@ -50,8 +51,8 @@ __COUNTER_MAX = 2**__COUNTER_BITS - 1
def warn_if_counter_may_have_saturated(dispatches_table): def warn_if_counter_may_have_saturated(dispatches_table):
for source, counters_from_source in dispatches_table.items(): for source, counters_from_source in iteritems(dispatches_table):
for destination, counter in counters_from_source.items(): for destination, counter in iteritems(counters_from_source):
if counter == __COUNTER_MAX: if counter == __COUNTER_MAX:
print "WARNING: {} -> {} may have saturated.".format(source, print "WARNING: {} -> {} may have saturated.".format(source,
destination) destination)
...@@ -59,8 +60,8 @@ def warn_if_counter_may_have_saturated(dispatches_table): ...@@ -59,8 +60,8 @@ def warn_if_counter_may_have_saturated(dispatches_table):
def find_top_bytecode_dispatch_pairs(dispatches_table, top_count): def find_top_bytecode_dispatch_pairs(dispatches_table, top_count):
def flattened_counters_generator(): def flattened_counters_generator():
for source, counters_from_source in dispatches_table.items(): for source, counters_from_source in iteritems(dispatches_table):
for destination, counter in counters_from_source.items(): for destination, counter in iteritems(counters_from_source):
yield source, destination, counter yield source, destination, counter
return heapq.nlargest(top_count, flattened_counters_generator(), return heapq.nlargest(top_count, flattened_counters_generator(),
...@@ -77,8 +78,9 @@ def print_top_bytecode_dispatch_pairs(dispatches_table, top_count): ...@@ -77,8 +78,9 @@ def print_top_bytecode_dispatch_pairs(dispatches_table, top_count):
def find_top_bytecodes(dispatches_table): def find_top_bytecodes(dispatches_table):
top_bytecodes = [] top_bytecodes = []
for bytecode, counters_from_bytecode in dispatches_table.items(): for bytecode, counters_from_bytecode in iteritems(dispatches_table):
top_bytecodes.append((bytecode, sum(counters_from_bytecode.values()))) top_bytecodes.append((bytecode, sum(itervalues(counters_from_bytecode))))
top_bytecodes.sort(key=lambda x: x[1], reverse=True) top_bytecodes.sort(key=lambda x: x[1], reverse=True)
return top_bytecodes return top_bytecodes
...@@ -90,30 +92,37 @@ def print_top_bytecodes(dispatches_table): ...@@ -90,30 +92,37 @@ def print_top_bytecodes(dispatches_table):
print "{:>12d}\t{}".format(counter, bytecode) print "{:>12d}\t{}".format(counter, bytecode)
def find_top_dispatch_sources(dispatches_table, destination, top_count): def find_top_dispatch_sources_and_destinations(
def source_counters_generator(): dispatches_table, bytecode, top_count, sort_source_relative):
for source, table_row in dispatches_table.items(): sources = []
if destination in table_row: for source, destinations in iteritems(dispatches_table):
yield source, table_row[destination] 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(), destinations = []
key=lambda x: x[1]) 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])
def print_top_dispatch_sources_and_destinations(dispatches_table, bytecode,
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) print "Top sources of dispatches to {}:".format(bytecode)
for source_name, counter in top_sources: for source_name, counter, ratio in top_sources:
print "{:>12d}\t{}".format(counter, source_name) print "{:>12d}\t{:>5.1f}%\t{}".format(counter, ratio * 100, source_name)
print "\nTop destinations of dispatches from {}:".format(bytecode) print "\nTop destinations of dispatches from {}:".format(bytecode)
for destination_name, counter in top_destinations: for destination_name, counter, ratio in top_destinations:
print "{:>12d}\t{}".format(counter, destination_name) print "{:>12d}\t{:>5.1f}%\t{}".format(counter, ratio * 100, destination_name)
def build_counters_matrix(dispatches_table): def build_counters_matrix(dispatches_table):
...@@ -214,6 +223,12 @@ def parse_command_line(): ...@@ -214,6 +223,12 @@ def parse_command_line():
help=("file to save the plot file to. File type is deduced from the " help=("file to save the plot file to. File type is deduced from the "
"extension. PDF, SVG, PNG supported") "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( command_line_parser.add_argument(
"input_filename", "input_filename",
metavar="<input filename>", metavar="<input filename>",
...@@ -225,6 +240,14 @@ def parse_command_line(): ...@@ -225,6 +240,14 @@ def parse_command_line():
return command_line_parser.parse_args() 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(): def main():
program_options = parse_command_line() program_options = parse_command_line()
...@@ -249,7 +272,7 @@ def main(): ...@@ -249,7 +272,7 @@ def main():
elif program_options.top_dispatches_for_bytecode: elif program_options.top_dispatches_for_bytecode:
print_top_dispatch_sources_and_destinations( print_top_dispatch_sources_and_destinations(
dispatches_table, program_options.top_dispatches_for_bytecode, dispatches_table, program_options.top_dispatches_for_bytecode,
program_options.top_entries_count) program_options.top_entries_count, program_options.sort_sources_relative)
else: else:
print_top_bytecodes(dispatches_table) print_top_bytecodes(dispatches_table)
......
...@@ -42,13 +42,21 @@ class BytecodeDispatchesReportTest(unittest.TestCase): ...@@ -42,13 +42,21 @@ class BytecodeDispatchesReportTest(unittest.TestCase):
('b', 5) ('b', 5)
]) ])
def test_find_top_dispatch_sources(self): def test_find_top_dispatch_sources_and_destinations(self):
top_dispatch_sources = bdr.find_top_dispatch_sources({ d = {
"a": {"a": 10, "b": 8, "c": 7}, "a": {"a": 4, "b": 2, "c": 4},
"b": {"a": 1, "c": 4}, "b": {"a": 1, "c": 4},
"c": {"a": 42, "b": 12, "c": 99} "c": {"a": 40, "b": 10, "c": 50}
}, "b", 10) }
self.assertListEqual(top_dispatch_sources, [ top_sources, top_dests = bdr.find_top_dispatch_sources_and_destinations(
("c", 12), d, "b", 10, False)
("a", 8) 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)
]) ])
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment