Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(10)

Side by Side Diff: tools/ignition_perf_report.py

Issue 1783503002: [Interpreter] Add Ignition profile visualization tool. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@run-perf
Patch Set: Avoid uneeded unpacking. Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #! /usr/bin/python2
2 #
Michael Achenbach 2016/03/10 11:50:36 nit: Not sure if presubmit allows this empty comme
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 re
9 import sys
10 import collections
Michael Achenbach 2016/03/10 11:50:36 nit: alpha order
11 import subprocess
12 import argparse
13
14
15 DESCRIPTION = """
16 Processes a perf.data sample file and reports the hottest Ignition bytecodes,
17 or write an input file for flamegraph.pl.
18 """
19
20
21 EPILOGUE = """
22 examples:
23 # Get a flamegraph for Ignition bytecode handlers on Octane benchmark,
24 # without considering time spent compiling JS code.
25 #
26 $ tools/run-perf.sh out/x64.release/d8 --ignition octane/run.js
27 $ tools/ignition_perf_report.py --flamegraph --hide-compile -o out.collapsed
28 $ flamegraph.pl --colors js out.collapsed > out.svg
29
30 # See the hottest bytecodes on Octane benchmark, by number of samples.
31 #
32 $ tools/run-perf.sh out/x64.release/d8 --ignition octane/run.js
33 $ tools/ignition_perf_report.py
34 """
35
36
37 COMPILER_SYMBOLS_RE = re.compile(r"Builtin:Compile(?:Lazy|OptimizedConcurrent)"
38 "$|LazyCompile:|v8::internal::Compile")
39
40
41 def yield_collapsed_callchains(perf_stream, hide_compile_time=False):
42 current_chain = []
43 keep_parsing_chain = True
44 for line in perf_stream:
45 if line[0] == "#": continue
46 line = line.strip()
47 if not line:
48 keep_parsing_chain = True
49 current_chain = []
50 continue
51 if not keep_parsing_chain: continue
52 symbol = line.split(" ", 1)[1]
53 # Strip the parameters from the signature (i.e. the parts between braces)
54 symbol = symbol[0] + symbol[1:].split("(", 1)[0]
55 current_chain.append(symbol)
56 if hide_compile_time and COMPILER_SYMBOLS_RE.match(symbol):
57 keep_parsing_chain = False
58 elif symbol.startswith("BytecodeHandler:"):
59 keep_parsing_chain = False
60 yield current_chain
61
62
63 def count_callchains(perf_stream, hide_compile_time):
64 chain_counters = collections.defaultdict(int)
65 for callchain in yield_collapsed_callchains(perf_stream, hide_compile_time):
66 key = ";".join(reversed(callchain))
67 chain_counters[key] += 1
68 return chain_counters.items()
69
70
71 def count_handler_samples(perf_stream, hide_compile_time):
72 handler_counters = collections.defaultdict(int)
73 for callchain in yield_collapsed_callchains(perf_stream, hide_compile_time):
74 # Strip the "BytecodeHandler:" prefix
75 handler = callchain[-1].split(":", 1)[1]
Michael Achenbach 2016/03/10 11:50:36 Assuming that there is no other : in callchain[-1]
76 handler_counters[handler] += 1
77 # Sort by decreasing number of samples
78 return sorted(handler_counters.items(),
79 key=lambda entry: entry[1], reverse=True)
80
81
82 def parse_command_line():
83 command_line_parser = argparse.ArgumentParser(
84 formatter_class=argparse.RawDescriptionHelpFormatter,
85 description=DESCRIPTION,
86 epilog=EPILOGUE)
87
88 command_line_parser.add_argument(
89 "perf_filename",
90 help="perf sample file to process (default: perf.data)",
91 nargs="?",
92 default="perf.data",
93 metavar="<perf filename>")
94 command_line_parser.add_argument(
95 "--flamegraph", "-f",
96 help="output an input file for flamegraph.pl, not a report",
97 action="store_true",
98 dest="output_flamegraph")
99 command_line_parser.add_argument(
100 "--hide-compile", "-c",
101 help="do not count samples inside compiler routines",
102 action="store_true",
103 dest="hide_compile_time")
104 command_line_parser.add_argument(
105 "--output", "-o",
106 help="output file name (stdout if omitted)",
107 type=argparse.FileType('wt'),
108 default=sys.stdout,
109 metavar="<output filename>",
110 dest="output_stream")
111
112 return command_line_parser.parse_args()
113
114
115 def main():
116 program_options = parse_command_line()
117 output_stream = program_options.output_stream
118 perf = subprocess.Popen(["perf", "script", "-f", "ip,sym",
119 "-i", program_options.perf_filename],
120 stdout=subprocess.PIPE)
121
122 if program_options.output_flamegraph:
123 callchain_counters = count_callchains(perf.stdout,
124 program_options.hide_compile_time)
125 for callchain, count in callchain_counters:
126 output_stream.write("{} {}\n".format(callchain, count))
127 else:
128 handler_counters = count_handler_samples(perf.stdout,
129 program_options.hide_compile_time)
130 samples_num = sum(counter for _, counter in handler_counters)
131 for bytecode_name, count in handler_counters:
132 output_stream.write(
133 "{}\t{}\t{:.3f}%\n".format(bytecode_name, count,
134 100. * count / samples_num))
135
136
137 if __name__ == "__main__":
138 main()
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698