brintos

brintos / linux-shallow public Read only

0
0
Text · 4.3 KiB · b1c4def Raw
128 lines · python
1# stackcollapse.py - format perf samples with one line per distinct call stack2# SPDX-License-Identifier: GPL-2.03#4# This script's output has two space-separated fields.  The first is a semicolon5# separated stack including the program name (from the "comm" field) and the6# function names from the call stack.  The second is a count:7#8#  swapper;start_kernel;rest_init;cpu_idle;default_idle;native_safe_halt 29#10# The file is sorted according to the first field.11#12# Input may be created and processed using:13#14#  perf record -a -g -F 99 sleep 6015#  perf script report stackcollapse > out.stacks-folded16#17# (perf script record stackcollapse works too).18#19# Written by Paolo Bonzini <pbonzini@redhat.com>20# Based on Brendan Gregg's stackcollapse-perf.pl script.21 22from __future__ import print_function23 24import os25import sys26from collections import defaultdict27from optparse import OptionParser, make_option28 29sys.path.append(os.environ['PERF_EXEC_PATH'] + \30    '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')31 32from perf_trace_context import *33from Core import *34from EventClass import *35 36# command line parsing37 38option_list = [39    # formatting options for the bottom entry of the stack40    make_option("--include-tid", dest="include_tid",41                 action="store_true", default=False,42                 help="include thread id in stack"),43    make_option("--include-pid", dest="include_pid",44                 action="store_true", default=False,45                 help="include process id in stack"),46    make_option("--no-comm", dest="include_comm",47                 action="store_false", default=True,48                 help="do not separate stacks according to comm"),49    make_option("--tidy-java", dest="tidy_java",50                 action="store_true", default=False,51                 help="beautify Java signatures"),52    make_option("--kernel", dest="annotate_kernel",53                 action="store_true", default=False,54                 help="annotate kernel functions with _[k]")55]56 57parser = OptionParser(option_list=option_list)58(opts, args) = parser.parse_args()59 60if len(args) != 0:61    parser.error("unexpected command line argument")62if opts.include_tid and not opts.include_comm:63    parser.error("requesting tid but not comm is invalid")64if opts.include_pid and not opts.include_comm:65    parser.error("requesting pid but not comm is invalid")66 67# event handlers68 69lines = defaultdict(lambda: 0)70 71def process_event(param_dict):72    def tidy_function_name(sym, dso):73        if sym is None:74            sym = '[unknown]'75 76        sym = sym.replace(';', ':')77        if opts.tidy_java:78            # the original stackcollapse-perf.pl script gives the79            # example of converting this:80            #    Lorg/mozilla/javascript/MemberBox;.<init>(Ljava/lang/reflect/Method;)V81            # to this:82            #    org/mozilla/javascript/MemberBox:.init83            sym = sym.replace('<', '')84            sym = sym.replace('>', '')85            if sym[0] == 'L' and sym.find('/'):86                sym = sym[1:]87            try:88                sym = sym[:sym.index('(')]89            except ValueError:90                pass91 92        if opts.annotate_kernel and dso == '[kernel.kallsyms]':93            return sym + '_[k]'94        else:95            return sym96 97    stack = list()98    if 'callchain' in param_dict:99        for entry in param_dict['callchain']:100            entry.setdefault('sym', dict())101            entry['sym'].setdefault('name', None)102            entry.setdefault('dso', None)103            stack.append(tidy_function_name(entry['sym']['name'],104                                            entry['dso']))105    else:106        param_dict.setdefault('symbol', None)107        param_dict.setdefault('dso', None)108        stack.append(tidy_function_name(param_dict['symbol'],109                                        param_dict['dso']))110 111    if opts.include_comm:112        comm = param_dict["comm"].replace(' ', '_')113        sep = "-"114        if opts.include_pid:115            comm = comm + sep + str(param_dict['sample']['pid'])116            sep = "/"117        if opts.include_tid:118            comm = comm + sep + str(param_dict['sample']['tid'])119        stack.append(comm)120 121    stack_string = ';'.join(reversed(stack))122    lines[stack_string] = lines[stack_string] + 1123 124def trace_end():125    list = sorted(lines)126    for stack in list:127        print("%s %d" % (stack, lines[stack]))128