OLD | NEW |
1 #! /usr/bin/python2 | 1 #! /usr/bin/python2 |
2 # | 2 # |
3 # Copyright 2016 the V8 project authors. All rights reserved. | 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 | 4 # Use of this source code is governed by a BSD-style license that can be |
5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
6 # | 6 # |
7 | 7 |
8 import argparse | 8 import argparse |
9 import collections | 9 import collections |
10 import re | 10 import re |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
47 $ tools/run-perf.sh out/x64.release/d8 \\ | 47 $ tools/run-perf.sh out/x64.release/d8 \\ |
48 --ignition --noturbo --nocrankshaft octane/run.js | 48 --ignition --noturbo --nocrankshaft octane/run.js |
49 $ tools/ignition/linux_perf_report.py | 49 $ tools/ignition/linux_perf_report.py |
50 """ | 50 """ |
51 | 51 |
52 | 52 |
53 COMPILER_SYMBOLS_RE = re.compile( | 53 COMPILER_SYMBOLS_RE = re.compile( |
54 r"v8::internal::(?:\(anonymous namespace\)::)?Compile|v8::internal::Parser") | 54 r"v8::internal::(?:\(anonymous namespace\)::)?Compile|v8::internal::Parser") |
55 JIT_CODE_SYMBOLS_RE = re.compile( | 55 JIT_CODE_SYMBOLS_RE = re.compile( |
56 r"(LazyCompile|Compile|Eval|Script):(\*|~)") | 56 r"(LazyCompile|Compile|Eval|Script):(\*|~)") |
| 57 GC_SYMBOLS_RE = re.compile( |
| 58 r"v8::internal::Heap::CollectGarbage") |
57 | 59 |
58 | 60 |
59 def strip_function_parameters(symbol): | 61 def strip_function_parameters(symbol): |
60 if symbol[-1] != ')': return symbol | 62 if symbol[-1] != ')': return symbol |
61 pos = 1 | 63 pos = 1 |
62 parenthesis_count = 0 | 64 parenthesis_count = 0 |
63 for c in reversed(symbol): | 65 for c in reversed(symbol): |
64 if c == ')': | 66 if c == ')': |
65 parenthesis_count += 1 | 67 parenthesis_count += 1 |
66 elif c == '(': | 68 elif c == '(': |
67 parenthesis_count -= 1 | 69 parenthesis_count -= 1 |
68 if parenthesis_count == 0: | 70 if parenthesis_count == 0: |
69 break | 71 break |
70 else: | 72 else: |
71 pos += 1 | 73 pos += 1 |
72 return symbol[:-pos] | 74 return symbol[:-pos] |
73 | 75 |
74 | 76 |
75 def collapsed_callchains_generator(perf_stream, hide_other=False, | 77 def collapsed_callchains_generator(perf_stream, hide_other=False, |
76 hide_compiler=False, hide_jit=False, | 78 hide_compiler=False, hide_jit=False, |
77 show_full_signatures=False): | 79 hide_gc=False, show_full_signatures=False): |
78 current_chain = [] | 80 current_chain = [] |
79 skip_until_end_of_chain = False | 81 skip_until_end_of_chain = False |
80 compiler_symbol_in_chain = False | 82 compiler_symbol_in_chain = False |
81 | 83 |
82 for line in perf_stream: | 84 for line in perf_stream: |
83 # Lines starting with a "#" are comments, skip them. | 85 # Lines starting with a "#" are comments, skip them. |
84 if line[0] == "#": | 86 if line[0] == "#": |
85 continue | 87 continue |
86 | 88 |
87 line = line.strip() | 89 line = line.strip() |
(...skipping 27 matching lines...) Expand all Loading... |
115 | 117 |
116 if symbol.startswith("BytecodeHandler:"): | 118 if symbol.startswith("BytecodeHandler:"): |
117 current_chain.append("[interpreter]") | 119 current_chain.append("[interpreter]") |
118 yield current_chain | 120 yield current_chain |
119 skip_until_end_of_chain = True | 121 skip_until_end_of_chain = True |
120 elif JIT_CODE_SYMBOLS_RE.match(symbol): | 122 elif JIT_CODE_SYMBOLS_RE.match(symbol): |
121 if not hide_jit: | 123 if not hide_jit: |
122 current_chain.append("[jit]") | 124 current_chain.append("[jit]") |
123 yield current_chain | 125 yield current_chain |
124 skip_until_end_of_chain = True | 126 skip_until_end_of_chain = True |
| 127 elif GC_SYMBOLS_RE.match(symbol): |
| 128 if not hide_gc: |
| 129 current_chain.append("[gc]") |
| 130 yield current_chain |
| 131 skip_until_end_of_chain = True |
125 elif symbol == "Stub:CEntryStub" and compiler_symbol_in_chain: | 132 elif symbol == "Stub:CEntryStub" and compiler_symbol_in_chain: |
126 if not hide_compiler: | 133 if not hide_compiler: |
127 current_chain.append("[compiler]") | 134 current_chain.append("[compiler]") |
128 yield current_chain | 135 yield current_chain |
129 skip_until_end_of_chain = True | 136 skip_until_end_of_chain = True |
130 elif COMPILER_SYMBOLS_RE.match(symbol): | 137 elif COMPILER_SYMBOLS_RE.match(symbol): |
131 compiler_symbol_in_chain = True | 138 compiler_symbol_in_chain = True |
132 elif symbol == "Builtin:InterpreterEntryTrampoline": | 139 elif symbol == "Builtin:InterpreterEntryTrampoline": |
133 if len(current_chain) == 1: | 140 if len(current_chain) == 1: |
134 yield ["[entry trampoline]"] | 141 yield ["[entry trampoline]"] |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
205 "--hide-compiler", | 212 "--hide-compiler", |
206 help="Hide samples during compilation", | 213 help="Hide samples during compilation", |
207 action="store_true" | 214 action="store_true" |
208 ) | 215 ) |
209 command_line_parser.add_argument( | 216 command_line_parser.add_argument( |
210 "--hide-jit", | 217 "--hide-jit", |
211 help="Hide samples from JIT code execution", | 218 help="Hide samples from JIT code execution", |
212 action="store_true" | 219 action="store_true" |
213 ) | 220 ) |
214 command_line_parser.add_argument( | 221 command_line_parser.add_argument( |
| 222 "--hide-gc", |
| 223 help="Hide samples from garbage collection", |
| 224 action="store_true" |
| 225 ) |
| 226 command_line_parser.add_argument( |
215 "--show-full-signatures", "-s", | 227 "--show-full-signatures", "-s", |
216 help="show full signatures instead of function names", | 228 help="show full signatures instead of function names", |
217 action="store_true" | 229 action="store_true" |
218 ) | 230 ) |
219 command_line_parser.add_argument( | 231 command_line_parser.add_argument( |
220 "--output", "-o", | 232 "--output", "-o", |
221 help="output file name (stdout if omitted)", | 233 help="output file name (stdout if omitted)", |
222 type=argparse.FileType('wt'), | 234 type=argparse.FileType('wt'), |
223 default=sys.stdout, | 235 default=sys.stdout, |
224 metavar="<output filename>", | 236 metavar="<output filename>", |
225 dest="output_stream" | 237 dest="output_stream" |
226 ) | 238 ) |
227 | 239 |
228 return command_line_parser.parse_args() | 240 return command_line_parser.parse_args() |
229 | 241 |
230 | 242 |
231 def main(): | 243 def main(): |
232 program_options = parse_command_line() | 244 program_options = parse_command_line() |
233 | 245 |
234 perf = subprocess.Popen(["perf", "script", "--fields", "ip,sym", | 246 perf = subprocess.Popen(["perf", "script", "--fields", "ip,sym", |
235 "-i", program_options.perf_filename], | 247 "-i", program_options.perf_filename], |
236 stdout=subprocess.PIPE) | 248 stdout=subprocess.PIPE) |
237 | 249 |
238 callchains = collapsed_callchains_generator( | 250 callchains = collapsed_callchains_generator( |
239 perf.stdout, program_options.hide_other, program_options.hide_compiler, | 251 perf.stdout, program_options.hide_other, program_options.hide_compiler, |
240 program_options.hide_jit, program_options.show_full_signatures) | 252 program_options.hide_jit, program_options.hide_gc, |
| 253 program_options.show_full_signatures) |
241 | 254 |
242 if program_options.output_flamegraph: | 255 if program_options.output_flamegraph: |
243 write_flamegraph_input_file(program_options.output_stream, callchains) | 256 write_flamegraph_input_file(program_options.output_stream, callchains) |
244 else: | 257 else: |
245 write_handlers_report(program_options.output_stream, callchains) | 258 write_handlers_report(program_options.output_stream, callchains) |
246 | 259 |
247 | 260 |
248 if __name__ == "__main__": | 261 if __name__ == "__main__": |
249 main() | 262 main() |
OLD | NEW |