diff options
| author | Ingo Molnar <mingo@kernel.org> | 2016-06-22 03:34:19 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2016-06-22 03:34:19 -0400 |
| commit | 4330b439bbe16b48dd2fe9a379bd58a07b97aab8 (patch) | |
| tree | 375958f5410db5095d172b21f02e5bb737fb97c6 /tools/perf/scripts/python | |
| parent | 02469a95096a549508c5adf61d84a1d72851c85b (diff) | |
| parent | 6745d8ea825966b0956c691cf7fccc13debedc39 (diff) | |
Merge tag 'perf-core-for-mingo-20160621' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:
New features:
- Add --dry-run option to 'perf record' to check if command line options can be
parsed, but not doing any recording (Wang Nan)
- Allow dumping the object files generated by llvm when processing eBPF
scriptlet events (Wang Nan)
- Add stackcollapse.py script to help generating flame graphs (Paolo Bonzini)
Documentation changes:
- Fix 'perf script' documentation of '-f' when it should be '-F' (Adrian Hunter)
Infrastructure changes:
- Fix write_backwards fallback when using a new tool on older kernels
without support for this feature (Arnaldo Carvalho de Melo)
- Remove some leftovers from the initial codebase copying from git
(Arnaldo Carvalho de Melo)
- List libelf-devel as an alternative, as this is how the libelf
development package is called on OpenSuSE (Jean Delvare)
- Rename __hists__add_entry to hists__add_entry (Jiri Olsa)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf/scripts/python')
| -rwxr-xr-x | tools/perf/scripts/python/bin/stackcollapse-record | 8 | ||||
| -rwxr-xr-x | tools/perf/scripts/python/bin/stackcollapse-report | 3 | ||||
| -rwxr-xr-x | tools/perf/scripts/python/stackcollapse.py | 127 |
3 files changed, 138 insertions, 0 deletions
diff --git a/tools/perf/scripts/python/bin/stackcollapse-record b/tools/perf/scripts/python/bin/stackcollapse-record new file mode 100755 index 000000000000..9d8f9f0f3a17 --- /dev/null +++ b/tools/perf/scripts/python/bin/stackcollapse-record | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | #!/bin/sh | ||
| 2 | |||
| 3 | # | ||
| 4 | # stackcollapse.py can cover all type of perf samples including | ||
| 5 | # the tracepoints, so no special record requirements, just record what | ||
| 6 | # you want to analyze. | ||
| 7 | # | ||
| 8 | perf record "$@" | ||
diff --git a/tools/perf/scripts/python/bin/stackcollapse-report b/tools/perf/scripts/python/bin/stackcollapse-report new file mode 100755 index 000000000000..356b9656393d --- /dev/null +++ b/tools/perf/scripts/python/bin/stackcollapse-report | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | #!/bin/sh | ||
| 2 | # description: produce callgraphs in short form for scripting use | ||
| 3 | perf script -s "$PERF_EXEC_PATH"/scripts/python/stackcollapse.py -- "$@" | ||
diff --git a/tools/perf/scripts/python/stackcollapse.py b/tools/perf/scripts/python/stackcollapse.py new file mode 100755 index 000000000000..a2dfcda41ae6 --- /dev/null +++ b/tools/perf/scripts/python/stackcollapse.py | |||
| @@ -0,0 +1,127 @@ | |||
| 1 | #!/usr/bin/perl -w | ||
| 2 | # | ||
| 3 | # stackcollapse.py - format perf samples with one line per distinct call stack | ||
| 4 | # | ||
| 5 | # This script's output has two space-separated fields. The first is a semicolon | ||
| 6 | # separated stack including the program name (from the "comm" field) and the | ||
| 7 | # function names from the call stack. The second is a count: | ||
| 8 | # | ||
| 9 | # swapper;start_kernel;rest_init;cpu_idle;default_idle;native_safe_halt 2 | ||
| 10 | # | ||
| 11 | # The file is sorted according to the first field. | ||
| 12 | # | ||
| 13 | # Input may be created and processed using: | ||
| 14 | # | ||
| 15 | # perf record -a -g -F 99 sleep 60 | ||
| 16 | # perf script report stackcollapse > out.stacks-folded | ||
| 17 | # | ||
| 18 | # (perf script record stackcollapse works too). | ||
| 19 | # | ||
| 20 | # Written by Paolo Bonzini <pbonzini@redhat.com> | ||
| 21 | # Based on Brendan Gregg's stackcollapse-perf.pl script. | ||
| 22 | |||
| 23 | import os | ||
| 24 | import sys | ||
| 25 | from collections import defaultdict | ||
| 26 | from optparse import OptionParser, make_option | ||
| 27 | |||
| 28 | sys.path.append(os.environ['PERF_EXEC_PATH'] + \ | ||
| 29 | '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') | ||
| 30 | |||
| 31 | from perf_trace_context import * | ||
| 32 | from Core import * | ||
| 33 | from EventClass import * | ||
| 34 | |||
| 35 | # command line parsing | ||
| 36 | |||
| 37 | option_list = [ | ||
| 38 | # formatting options for the bottom entry of the stack | ||
| 39 | make_option("--include-tid", dest="include_tid", | ||
| 40 | action="store_true", default=False, | ||
| 41 | help="include thread id in stack"), | ||
| 42 | make_option("--include-pid", dest="include_pid", | ||
| 43 | action="store_true", default=False, | ||
| 44 | help="include process id in stack"), | ||
| 45 | make_option("--no-comm", dest="include_comm", | ||
| 46 | action="store_false", default=True, | ||
| 47 | help="do not separate stacks according to comm"), | ||
| 48 | make_option("--tidy-java", dest="tidy_java", | ||
| 49 | action="store_true", default=False, | ||
| 50 | help="beautify Java signatures"), | ||
| 51 | make_option("--kernel", dest="annotate_kernel", | ||
| 52 | action="store_true", default=False, | ||
| 53 | help="annotate kernel functions with _[k]") | ||
| 54 | ] | ||
| 55 | |||
| 56 | parser = OptionParser(option_list=option_list) | ||
| 57 | (opts, args) = parser.parse_args() | ||
| 58 | |||
| 59 | if len(args) != 0: | ||
| 60 | parser.error("unexpected command line argument") | ||
| 61 | if opts.include_tid and not opts.include_comm: | ||
| 62 | parser.error("requesting tid but not comm is invalid") | ||
| 63 | if opts.include_pid and not opts.include_comm: | ||
| 64 | parser.error("requesting pid but not comm is invalid") | ||
| 65 | |||
| 66 | # event handlers | ||
| 67 | |||
| 68 | lines = defaultdict(lambda: 0) | ||
| 69 | |||
| 70 | def process_event(param_dict): | ||
| 71 | def tidy_function_name(sym, dso): | ||
| 72 | if sym is None: | ||
| 73 | sym = '[unknown]' | ||
| 74 | |||
| 75 | sym = sym.replace(';', ':') | ||
| 76 | if opts.tidy_java: | ||
| 77 | # the original stackcollapse-perf.pl script gives the | ||
| 78 | # example of converting this: | ||
| 79 | # Lorg/mozilla/javascript/MemberBox;.<init>(Ljava/lang/reflect/Method;)V | ||
| 80 | # to this: | ||
| 81 | # org/mozilla/javascript/MemberBox:.init | ||
| 82 | sym = sym.replace('<', '') | ||
| 83 | sym = sym.replace('>', '') | ||
| 84 | if sym[0] == 'L' and sym.find('/'): | ||
| 85 | sym = sym[1:] | ||
| 86 | try: | ||
| 87 | sym = sym[:sym.index('(')] | ||
| 88 | except ValueError: | ||
| 89 | pass | ||
| 90 | |||
| 91 | if opts.annotate_kernel and dso == '[kernel.kallsyms]': | ||
| 92 | return sym + '_[k]' | ||
| 93 | else: | ||
| 94 | return sym | ||
| 95 | |||
| 96 | stack = list() | ||
| 97 | if 'callchain' in param_dict: | ||
| 98 | for entry in param_dict['callchain']: | ||
| 99 | entry.setdefault('sym', dict()) | ||
| 100 | entry['sym'].setdefault('name', None) | ||
| 101 | entry.setdefault('dso', None) | ||
| 102 | stack.append(tidy_function_name(entry['sym']['name'], | ||
| 103 | entry['dso'])) | ||
| 104 | else: | ||
| 105 | param_dict.setdefault('symbol', None) | ||
| 106 | param_dict.setdefault('dso', None) | ||
| 107 | stack.append(tidy_function_name(param_dict['symbol'], | ||
| 108 | param_dict['dso'])) | ||
| 109 | |||
| 110 | if opts.include_comm: | ||
| 111 | comm = param_dict["comm"].replace(' ', '_') | ||
| 112 | sep = "-" | ||
| 113 | if opts.include_pid: | ||
| 114 | comm = comm + sep + str(param_dict['sample']['pid']) | ||
| 115 | sep = "/" | ||
| 116 | if opts.include_tid: | ||
| 117 | comm = comm + sep + str(param_dict['sample']['tid']) | ||
| 118 | stack.append(comm) | ||
| 119 | |||
| 120 | stack_string = ';'.join(reversed(stack)) | ||
| 121 | lines[stack_string] = lines[stack_string] + 1 | ||
| 122 | |||
| 123 | def trace_end(): | ||
| 124 | list = lines.keys() | ||
| 125 | list.sort() | ||
| 126 | for stack in list: | ||
| 127 | print "%s %d" % (stack, lines[stack]) | ||
