Commit 4bc082f3 authored by rmcilroy's avatar rmcilroy Committed by Commit bot

[Tools] Enable grouping of jited code in linux_perf_report.py.

Review-Url: https://codereview.chromium.org/2477363002
Cr-Commit-Position: refs/heads/master@{#40823}
parent 0ab9ecc2
...@@ -52,6 +52,8 @@ examples: ...@@ -52,6 +52,8 @@ examples:
COMPILER_SYMBOLS_RE = re.compile( COMPILER_SYMBOLS_RE = re.compile(
r"v8::internal::(?:\(anonymous namespace\)::)?Compile|v8::internal::Parser") r"v8::internal::(?:\(anonymous namespace\)::)?Compile|v8::internal::Parser")
JIT_CODE_SYMBOLS_RE = re.compile(
r"(LazyCompile|Compile|Eval|Script):(\*|~)")
def strip_function_parameters(symbol): def strip_function_parameters(symbol):
...@@ -70,7 +72,8 @@ def strip_function_parameters(symbol): ...@@ -70,7 +72,8 @@ def strip_function_parameters(symbol):
return symbol[:-pos] return symbol[:-pos]
def collapsed_callchains_generator(perf_stream, show_all=False, def collapsed_callchains_generator(perf_stream, hide_other=False,
hide_compiler=False, hide_jit=False,
show_full_signatures=False): show_full_signatures=False):
current_chain = [] current_chain = []
skip_until_end_of_chain = False skip_until_end_of_chain = False
...@@ -85,7 +88,8 @@ def collapsed_callchains_generator(perf_stream, show_all=False, ...@@ -85,7 +88,8 @@ def collapsed_callchains_generator(perf_stream, show_all=False,
# Empty line signals the end of the callchain. # Empty line signals the end of the callchain.
if not line: if not line:
if not skip_until_end_of_chain and current_chain and show_all: if (not skip_until_end_of_chain and current_chain
and not hide_other):
current_chain.append("[other]") current_chain.append("[other]")
yield current_chain yield current_chain
# Reset parser status. # Reset parser status.
...@@ -101,14 +105,26 @@ def collapsed_callchains_generator(perf_stream, show_all=False, ...@@ -101,14 +105,26 @@ def collapsed_callchains_generator(perf_stream, show_all=False,
symbol = line.split(" ", 1)[1].split("+", 1)[0] symbol = line.split(" ", 1)[1].split("+", 1)[0]
if not show_full_signatures: if not show_full_signatures:
symbol = strip_function_parameters(symbol) symbol = strip_function_parameters(symbol)
# Avoid chains of [unknown]
if (symbol == "[unknown]" and current_chain and
current_chain[-1] == "[unknown]"):
continue
current_chain.append(symbol) current_chain.append(symbol)
if symbol.startswith("BytecodeHandler:"): if symbol.startswith("BytecodeHandler:"):
current_chain.append("[interpreter]")
yield current_chain yield current_chain
skip_until_end_of_chain = True skip_until_end_of_chain = True
elif JIT_CODE_SYMBOLS_RE.match(symbol):
if not hide_jit:
current_chain.append("[jit]")
yield current_chain
skip_until_end_of_chain = True
elif symbol == "Stub:CEntryStub" and compiler_symbol_in_chain: elif symbol == "Stub:CEntryStub" and compiler_symbol_in_chain:
if show_all: if not hide_compiler:
current_chain[-1] = "[compiler]" current_chain.append("[compiler]")
yield current_chain yield current_chain
skip_until_end_of_chain = True skip_until_end_of_chain = True
elif COMPILER_SYMBOLS_RE.match(symbol): elif COMPILER_SYMBOLS_RE.match(symbol):
...@@ -181,8 +197,18 @@ def parse_command_line(): ...@@ -181,8 +197,18 @@ def parse_command_line():
dest="output_flamegraph" dest="output_flamegraph"
) )
command_line_parser.add_argument( command_line_parser.add_argument(
"--show-all", "-a", "--hide-other",
help="show samples outside Ignition bytecode handlers", help="Hide other samples",
action="store_true"
)
command_line_parser.add_argument(
"--hide-compiler",
help="Hide samples during compilation",
action="store_true"
)
command_line_parser.add_argument(
"--hide-jit",
help="Hide samples from JIT code execution",
action="store_true" action="store_true"
) )
command_line_parser.add_argument( command_line_parser.add_argument(
...@@ -210,8 +236,8 @@ def main(): ...@@ -210,8 +236,8 @@ def main():
stdout=subprocess.PIPE) stdout=subprocess.PIPE)
callchains = collapsed_callchains_generator( callchains = collapsed_callchains_generator(
perf.stdout, program_options.show_all, perf.stdout, program_options.hide_other, program_options.hide_compiler,
program_options.show_full_signatures) program_options.hide_jit, program_options.show_full_signatures)
if program_options.output_flamegraph: if program_options.output_flamegraph:
write_flamegraph_input_file(program_options.output_stream, callchains) write_flamegraph_input_file(program_options.output_stream, callchains)
......
...@@ -40,6 +40,9 @@ PERF_SCRIPT_OUTPUT = """ ...@@ -40,6 +40,9 @@ PERF_SCRIPT_OUTPUT = """
11111111 Builtin:InterpreterEntryTrampoline 11111111 Builtin:InterpreterEntryTrampoline
22222222 bar 22222222 bar
00000000 hello
11111111 LazyCompile:~Foo
11111111 Builtin:InterpreterEntryTrampoline 11111111 Builtin:InterpreterEntryTrampoline
22222222 bar 22222222 bar
""" """
...@@ -50,22 +53,26 @@ class LinuxPerfReportTest(unittest.TestCase): ...@@ -50,22 +53,26 @@ class LinuxPerfReportTest(unittest.TestCase):
perf_stream = StringIO.StringIO(PERF_SCRIPT_OUTPUT) perf_stream = StringIO.StringIO(PERF_SCRIPT_OUTPUT)
callchains = list(ipr.collapsed_callchains_generator(perf_stream)) callchains = list(ipr.collapsed_callchains_generator(perf_stream))
self.assertListEqual(callchains, [ self.assertListEqual(callchains, [
["foo", "BytecodeHandler:bar"], ['firstSymbol', 'secondSymbol', '[other]'],
["foo", "BytecodeHandler:bar"], ["foo", "BytecodeHandler:bar", "[interpreter]"],
["beep", "BytecodeHandler:bar"], ["foo", "BytecodeHandler:bar", "[interpreter]"],
["beep", "BytecodeHandler:bar", "[interpreter]"],
["hello", "v8::internal::Compiler", "Stub:CEntryStub", "[compiler]"],
["Lost", "[misattributed]"],
["hello", "LazyCompile:~Foo", "[jit]"],
["[entry trampoline]"], ["[entry trampoline]"],
]) ])
def test_collapsed_callchains_generator_show_other(self): def test_collapsed_callchains_generator_hide_other(self):
perf_stream = StringIO.StringIO(PERF_SCRIPT_OUTPUT) perf_stream = StringIO.StringIO(PERF_SCRIPT_OUTPUT)
callchains = list(ipr.collapsed_callchains_generator(perf_stream, callchains = list(ipr.collapsed_callchains_generator(perf_stream,
show_all=True)) hide_other=True,
hide_compiler=True,
hide_jit=True))
self.assertListEqual(callchains, [ self.assertListEqual(callchains, [
['firstSymbol', 'secondSymbol', '[other]'], ["foo", "BytecodeHandler:bar", "[interpreter]"],
["foo", "BytecodeHandler:bar"], ["foo", "BytecodeHandler:bar", "[interpreter]"],
["foo", "BytecodeHandler:bar"], ["beep", "BytecodeHandler:bar", "[interpreter]"],
["beep", "BytecodeHandler:bar"],
["hello", "v8::internal::Compiler", "[compiler]"],
["Lost", "[misattributed]"], ["Lost", "[misattributed]"],
["[entry trampoline]"], ["[entry trampoline]"],
]) ])
...@@ -125,7 +132,7 @@ class LinuxPerfReportTest(unittest.TestCase): ...@@ -125,7 +132,7 @@ class LinuxPerfReportTest(unittest.TestCase):
""") """)
callchains = list(ipr.collapsed_callchains_generator(perf_stream, False)) callchains = list(ipr.collapsed_callchains_generator(perf_stream, False))
self.assertListEqual(callchains, [ self.assertListEqual(callchains, [
["foo", "BytecodeHandler:first"], ["foo", "BytecodeHandler:first", "[interpreter]"],
]) ])
def test_compiler_symbols_regex(self): def test_compiler_symbols_regex(self):
...@@ -137,6 +144,15 @@ class LinuxPerfReportTest(unittest.TestCase): ...@@ -137,6 +144,15 @@ class LinuxPerfReportTest(unittest.TestCase):
for compiler_symbol in compiler_symbols: for compiler_symbol in compiler_symbols:
self.assertTrue(ipr.COMPILER_SYMBOLS_RE.match(compiler_symbol)) self.assertTrue(ipr.COMPILER_SYMBOLS_RE.match(compiler_symbol))
def test_jit_code_symbols_regex(self):
jit_code_symbols = [
"LazyCompile:~Foo blah.js",
"Eval:*",
"Script:*Bar tmp.js",
]
for jit_code_symbol in jit_code_symbols:
self.assertTrue(ipr.JIT_CODE_SYMBOLS_RE.match(jit_code_symbol))
def test_strip_function_parameters(self): def test_strip_function_parameters(self):
def should_match(signature, name): def should_match(signature, name):
self.assertEqual(ipr.strip_function_parameters(signature), name) self.assertEqual(ipr.strip_function_parameters(signature), name)
...@@ -145,3 +161,6 @@ class LinuxPerfReportTest(unittest.TestCase): ...@@ -145,3 +161,6 @@ class LinuxPerfReportTest(unittest.TestCase):
should_match("Foo(foomatic::(anonymous)::bar(baz))", "Foo"), should_match("Foo(foomatic::(anonymous)::bar(baz))", "Foo"),
should_match("v8::(anonymous ns)::bar<thing(with, parentheses)>(baz, poe)", should_match("v8::(anonymous ns)::bar<thing(with, parentheses)>(baz, poe)",
"v8::(anonymous ns)::bar<thing(with, parentheses)>") "v8::(anonymous ns)::bar<thing(with, parentheses)>")
if __name__ == '__main__':
unittest.main()
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