| # Copyright 2016 the V8 project authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import linux_perf_report as ipr |
| import StringIO |
| import unittest |
| |
| |
| PERF_SCRIPT_OUTPUT = """ |
| # This line is a comment |
| # This should be ignored too |
| # |
| # cdefab01 aRandomSymbol::Name(to, be, ignored) |
| |
| 00000000 firstSymbol |
| 00000123 secondSymbol |
| |
| 01234567 foo |
| abcdef76 BytecodeHandler:bar |
| 76543210 baz |
| |
| # Indentation shouldn't matter (neither should this line) |
| |
| 01234567 foo |
| abcdef76 BytecodeHandler:bar |
| 76543210 baz |
| |
| 01234567 beep |
| abcdef76 BytecodeHandler:bar |
| 76543210 baz |
| |
| 01234567 hello |
| abcdef76 v8::internal::Compiler |
| 00000000 Stub:CEntryStub |
| 76543210 world |
| 11111111 BytecodeHandler:nope |
| |
| 00000000 Lost |
| 11111111 Builtin:InterpreterEntryTrampoline |
| 22222222 bar |
| |
| 00000000 hello |
| 11111111 LazyCompile:~Foo |
| |
| 11111111 Builtin:InterpreterEntryTrampoline |
| 22222222 bar |
| """ |
| |
| |
| class LinuxPerfReportTest(unittest.TestCase): |
| def test_collapsed_callchains_generator(self): |
| perf_stream = StringIO.StringIO(PERF_SCRIPT_OUTPUT) |
| callchains = list(ipr.collapsed_callchains_generator(perf_stream)) |
| self.assertListEqual(callchains, [ |
| ['firstSymbol', 'secondSymbol', '[other]'], |
| ["foo", "BytecodeHandler:bar", "[interpreter]"], |
| ["foo", "BytecodeHandler:bar", "[interpreter]"], |
| ["beep", "BytecodeHandler:bar", "[interpreter]"], |
| ["hello", "v8::internal::Compiler", "Stub:CEntryStub", "[compiler]"], |
| ["Lost", "[misattributed]"], |
| ["hello", "LazyCompile:~Foo", "[jit]"], |
| ["[entry trampoline]"], |
| ]) |
| |
| def test_collapsed_callchains_generator_hide_other(self): |
| perf_stream = StringIO.StringIO(PERF_SCRIPT_OUTPUT) |
| callchains = list(ipr.collapsed_callchains_generator(perf_stream, |
| hide_other=True, |
| hide_compiler=True, |
| hide_jit=True)) |
| self.assertListEqual(callchains, [ |
| ["foo", "BytecodeHandler:bar", "[interpreter]"], |
| ["foo", "BytecodeHandler:bar", "[interpreter]"], |
| ["beep", "BytecodeHandler:bar", "[interpreter]"], |
| ["Lost", "[misattributed]"], |
| ["[entry trampoline]"], |
| ]) |
| |
| def test_calculate_samples_count_per_callchain(self): |
| counters = ipr.calculate_samples_count_per_callchain([ |
| ["foo", "BytecodeHandler:bar"], |
| ["foo", "BytecodeHandler:bar"], |
| ["beep", "BytecodeHandler:bar"], |
| ["hello", "v8::internal::Compiler", "[compiler]"], |
| ]) |
| self.assertItemsEqual(counters, [ |
| ('BytecodeHandler:bar;foo', 2), |
| ('BytecodeHandler:bar;beep', 1), |
| ('[compiler];v8::internal::Compiler;hello', 1), |
| ]) |
| |
| def test_calculate_samples_count_per_callchain(self): |
| counters = ipr.calculate_samples_count_per_callchain([ |
| ["foo", "BytecodeHandler:bar"], |
| ["foo", "BytecodeHandler:bar"], |
| ["beep", "BytecodeHandler:bar"], |
| ]) |
| self.assertItemsEqual(counters, [ |
| ('BytecodeHandler:bar;foo', 2), |
| ('BytecodeHandler:bar;beep', 1), |
| ]) |
| |
| def test_calculate_samples_count_per_handler_show_compile(self): |
| counters = ipr.calculate_samples_count_per_handler([ |
| ["foo", "BytecodeHandler:bar"], |
| ["foo", "BytecodeHandler:bar"], |
| ["beep", "BytecodeHandler:bar"], |
| ["hello", "v8::internal::Compiler", "[compiler]"], |
| ]) |
| self.assertItemsEqual(counters, [ |
| ("bar", 3), |
| ("[compiler]", 1) |
| ]) |
| |
| def test_calculate_samples_count_per_handler_(self): |
| counters = ipr.calculate_samples_count_per_handler([ |
| ["foo", "BytecodeHandler:bar"], |
| ["foo", "BytecodeHandler:bar"], |
| ["beep", "BytecodeHandler:bar"], |
| ]) |
| self.assertItemsEqual(counters, [("bar", 3)]) |
| |
| def test_multiple_handlers(self): |
| perf_stream = StringIO.StringIO(""" |
| 0000 foo(bar) |
| 1234 BytecodeHandler:first |
| 5678 a::random::call<to>(something, else) |
| 9abc BytecodeHandler:second |
| def0 otherIrrelevant(stuff) |
| 1111 entrypoint |
| """) |
| callchains = list(ipr.collapsed_callchains_generator(perf_stream, False)) |
| self.assertListEqual(callchains, [ |
| ["foo", "BytecodeHandler:first", "[interpreter]"], |
| ]) |
| |
| def test_compiler_symbols_regex(self): |
| compiler_symbols = [ |
| "v8::internal::Parser", |
| "v8::internal::(anonymous namespace)::Compile", |
| "v8::internal::Compiler::foo", |
| ] |
| for compiler_symbol in compiler_symbols: |
| 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 should_match(signature, name): |
| self.assertEqual(ipr.strip_function_parameters(signature), name) |
| |
| should_match("foo(bar)", "foo"), |
| should_match("Foo(foomatic::(anonymous)::bar(baz))", "Foo"), |
| should_match("v8::(anonymous ns)::bar<thing(with, parentheses)>(baz, poe)", |
| "v8::(anonymous ns)::bar<thing(with, parentheses)>") |
| |
| if __name__ == '__main__': |
| unittest.main() |