1 # stackcollapse.py - format perf samples with one line per distinct call stack
3 # This script's output has two space-separated fields. The first is a semicolon
4 # separated stack including the program name (from the "comm" field) and the
5 # function names from the call stack. The second is a count:
7 # swapper;start_kernel;rest_init;cpu_idle;default_idle;native_safe_halt 2
9 # The file is sorted according to the first field.
11 # Input may be created and processed using:
13 # perf record -a -g -F 99 sleep 60
14 # perf script report stackcollapse > out.stacks-folded
16 # (perf script record stackcollapse works too).
18 # Written by Paolo Bonzini <pbonzini@redhat.com>
19 # Based on Brendan Gregg's stackcollapse-perf.pl script.
23 from collections
import defaultdict
24 from optparse
import OptionParser
, make_option
26 sys
.path
.append(os
.environ
['PERF_EXEC_PATH'] + \
27 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
29 from perf_trace_context
import *
31 from EventClass
import *
33 # command line parsing
36 # formatting options for the bottom entry of the stack
37 make_option("--include-tid", dest
="include_tid",
38 action
="store_true", default
=False,
39 help="include thread id in stack"),
40 make_option("--include-pid", dest
="include_pid",
41 action
="store_true", default
=False,
42 help="include process id in stack"),
43 make_option("--no-comm", dest
="include_comm",
44 action
="store_false", default
=True,
45 help="do not separate stacks according to comm"),
46 make_option("--tidy-java", dest
="tidy_java",
47 action
="store_true", default
=False,
48 help="beautify Java signatures"),
49 make_option("--kernel", dest
="annotate_kernel",
50 action
="store_true", default
=False,
51 help="annotate kernel functions with _[k]")
54 parser
= OptionParser(option_list
=option_list
)
55 (opts
, args
) = parser
.parse_args()
58 parser
.error("unexpected command line argument")
59 if opts
.include_tid
and not opts
.include_comm
:
60 parser
.error("requesting tid but not comm is invalid")
61 if opts
.include_pid
and not opts
.include_comm
:
62 parser
.error("requesting pid but not comm is invalid")
66 lines
= defaultdict(lambda: 0)
68 def process_event(param_dict
):
69 def tidy_function_name(sym
, dso
):
73 sym
= sym
.replace(';', ':')
75 # the original stackcollapse-perf.pl script gives the
76 # example of converting this:
77 # Lorg/mozilla/javascript/MemberBox;.<init>(Ljava/lang/reflect/Method;)V
79 # org/mozilla/javascript/MemberBox:.init
80 sym
= sym
.replace('<', '')
81 sym
= sym
.replace('>', '')
82 if sym
[0] == 'L' and sym
.find('/'):
85 sym
= sym
[:sym
.index('(')]
89 if opts
.annotate_kernel
and dso
== '[kernel.kallsyms]':
95 if 'callchain' in param_dict
:
96 for entry
in param_dict
['callchain']:
97 entry
.setdefault('sym', dict())
98 entry
['sym'].setdefault('name', None)
99 entry
.setdefault('dso', None)
100 stack
.append(tidy_function_name(entry
['sym']['name'],
103 param_dict
.setdefault('symbol', None)
104 param_dict
.setdefault('dso', None)
105 stack
.append(tidy_function_name(param_dict
['symbol'],
108 if opts
.include_comm
:
109 comm
= param_dict
["comm"].replace(' ', '_')
112 comm
= comm
+ sep
+ str(param_dict
['sample']['pid'])
115 comm
= comm
+ sep
+ str(param_dict
['sample']['tid'])
118 stack_string
= ';'.join(reversed(stack
))
119 lines
[stack_string
] = lines
[stack_string
] + 1
125 print "%s %d" % (stack
, lines
[stack
])