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