linux/tools/perf/scripts/python/stackcollapse.py
Tony Jones b504d7f687 perf script python: Remove mixed indentation
Remove mixed indentation in Python scripts.  Revert to either all tabs
(most common form) or all spaces (4 or 8) depending on what was the
intent of the original commit.  This is necessary to complete Python3
support as it will flag an error if it encounters mixed indentation.

Signed-off-by: Tony Jones <tonyj@suse.de>
Link: http://lkml.kernel.org/r/20190302011903.2416-2-tonyj@suse.de
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-03-06 18:09:14 -03:00

128 lines
4.3 KiB
Python
Executable File

# stackcollapse.py - format perf samples with one line per distinct call stack
# SPDX-License-Identifier: GPL-2.0
#
# This script's output has two space-separated fields. The first is a semicolon
# separated stack including the program name (from the "comm" field) and the
# function names from the call stack. The second is a count:
#
# swapper;start_kernel;rest_init;cpu_idle;default_idle;native_safe_halt 2
#
# The file is sorted according to the first field.
#
# Input may be created and processed using:
#
# perf record -a -g -F 99 sleep 60
# perf script report stackcollapse > out.stacks-folded
#
# (perf script record stackcollapse works too).
#
# Written by Paolo Bonzini <pbonzini@redhat.com>
# Based on Brendan Gregg's stackcollapse-perf.pl script.
from __future__ import print_function
import os
import sys
from collections import defaultdict
from optparse import OptionParser, make_option
sys.path.append(os.environ['PERF_EXEC_PATH'] + \
'/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
from perf_trace_context import *
from Core import *
from EventClass import *
# command line parsing
option_list = [
# formatting options for the bottom entry of the stack
make_option("--include-tid", dest="include_tid",
action="store_true", default=False,
help="include thread id in stack"),
make_option("--include-pid", dest="include_pid",
action="store_true", default=False,
help="include process id in stack"),
make_option("--no-comm", dest="include_comm",
action="store_false", default=True,
help="do not separate stacks according to comm"),
make_option("--tidy-java", dest="tidy_java",
action="store_true", default=False,
help="beautify Java signatures"),
make_option("--kernel", dest="annotate_kernel",
action="store_true", default=False,
help="annotate kernel functions with _[k]")
]
parser = OptionParser(option_list=option_list)
(opts, args) = parser.parse_args()
if len(args) != 0:
parser.error("unexpected command line argument")
if opts.include_tid and not opts.include_comm:
parser.error("requesting tid but not comm is invalid")
if opts.include_pid and not opts.include_comm:
parser.error("requesting pid but not comm is invalid")
# event handlers
lines = defaultdict(lambda: 0)
def process_event(param_dict):
def tidy_function_name(sym, dso):
if sym is None:
sym = '[unknown]'
sym = sym.replace(';', ':')
if opts.tidy_java:
# the original stackcollapse-perf.pl script gives the
# example of converting this:
# Lorg/mozilla/javascript/MemberBox;.<init>(Ljava/lang/reflect/Method;)V
# to this:
# org/mozilla/javascript/MemberBox:.init
sym = sym.replace('<', '')
sym = sym.replace('>', '')
if sym[0] == 'L' and sym.find('/'):
sym = sym[1:]
try:
sym = sym[:sym.index('(')]
except ValueError:
pass
if opts.annotate_kernel and dso == '[kernel.kallsyms]':
return sym + '_[k]'
else:
return sym
stack = list()
if 'callchain' in param_dict:
for entry in param_dict['callchain']:
entry.setdefault('sym', dict())
entry['sym'].setdefault('name', None)
entry.setdefault('dso', None)
stack.append(tidy_function_name(entry['sym']['name'],
entry['dso']))
else:
param_dict.setdefault('symbol', None)
param_dict.setdefault('dso', None)
stack.append(tidy_function_name(param_dict['symbol'],
param_dict['dso']))
if opts.include_comm:
comm = param_dict["comm"].replace(' ', '_')
sep = "-"
if opts.include_pid:
comm = comm + sep + str(param_dict['sample']['pid'])
sep = "/"
if opts.include_tid:
comm = comm + sep + str(param_dict['sample']['tid'])
stack.append(comm)
stack_string = ';'.join(reversed(stack))
lines[stack_string] = lines[stack_string] + 1
def trace_end():
list = sorted(lines)
for stack in list:
print("%s %d" % (stack, lines[stack]))