Back to home page

OSCL-LXR

 
 

    


0001 # event_analyzing_sample.py: general event handler in python
0002 # SPDX-License-Identifier: GPL-2.0
0003 #
0004 # Current perf report is already very powerful with the annotation integrated,
0005 # and this script is not trying to be as powerful as perf report, but
0006 # providing end user/developer a flexible way to analyze the events other
0007 # than trace points.
0008 #
0009 # The 2 database related functions in this script just show how to gather
0010 # the basic information, and users can modify and write their own functions
0011 # according to their specific requirement.
0012 #
0013 # The first function "show_general_events" just does a basic grouping for all
0014 # generic events with the help of sqlite, and the 2nd one "show_pebs_ll" is
0015 # for a x86 HW PMU event: PEBS with load latency data.
0016 #
0017 
0018 from __future__ import print_function
0019 
0020 import os
0021 import sys
0022 import math
0023 import struct
0024 import sqlite3
0025 
0026 sys.path.append(os.environ['PERF_EXEC_PATH'] + \
0027         '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
0028 
0029 from perf_trace_context import *
0030 from EventClass import *
0031 
0032 #
0033 # If the perf.data has a big number of samples, then the insert operation
0034 # will be very time consuming (about 10+ minutes for 10000 samples) if the
0035 # .db database is on disk. Move the .db file to RAM based FS to speedup
0036 # the handling, which will cut the time down to several seconds.
0037 #
0038 con = sqlite3.connect("/dev/shm/perf.db")
0039 con.isolation_level = None
0040 
0041 def trace_begin():
0042         print("In trace_begin:\n")
0043 
0044         #
0045         # Will create several tables at the start, pebs_ll is for PEBS data with
0046         # load latency info, while gen_events is for general event.
0047         #
0048         con.execute("""
0049                 create table if not exists gen_events (
0050                         name text,
0051                         symbol text,
0052                         comm text,
0053                         dso text
0054                 );""")
0055         con.execute("""
0056                 create table if not exists pebs_ll (
0057                         name text,
0058                         symbol text,
0059                         comm text,
0060                         dso text,
0061                         flags integer,
0062                         ip integer,
0063                         status integer,
0064                         dse integer,
0065                         dla integer,
0066                         lat integer
0067                 );""")
0068 
0069 #
0070 # Create and insert event object to a database so that user could
0071 # do more analysis with simple database commands.
0072 #
0073 def process_event(param_dict):
0074         event_attr = param_dict["attr"]
0075         sample     = param_dict["sample"]
0076         raw_buf    = param_dict["raw_buf"]
0077         comm       = param_dict["comm"]
0078         name       = param_dict["ev_name"]
0079 
0080         # Symbol and dso info are not always resolved
0081         if ("dso" in param_dict):
0082                 dso = param_dict["dso"]
0083         else:
0084                 dso = "Unknown_dso"
0085 
0086         if ("symbol" in param_dict):
0087                 symbol = param_dict["symbol"]
0088         else:
0089                 symbol = "Unknown_symbol"
0090 
0091         # Create the event object and insert it to the right table in database
0092         event = create_event(name, comm, dso, symbol, raw_buf)
0093         insert_db(event)
0094 
0095 def insert_db(event):
0096         if event.ev_type == EVTYPE_GENERIC:
0097                 con.execute("insert into gen_events values(?, ?, ?, ?)",
0098                                 (event.name, event.symbol, event.comm, event.dso))
0099         elif event.ev_type == EVTYPE_PEBS_LL:
0100                 event.ip &= 0x7fffffffffffffff
0101                 event.dla &= 0x7fffffffffffffff
0102                 con.execute("insert into pebs_ll values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
0103                         (event.name, event.symbol, event.comm, event.dso, event.flags,
0104                                 event.ip, event.status, event.dse, event.dla, event.lat))
0105 
0106 def trace_end():
0107         print("In trace_end:\n")
0108         # We show the basic info for the 2 type of event classes
0109         show_general_events()
0110         show_pebs_ll()
0111         con.close()
0112 
0113 #
0114 # As the event number may be very big, so we can't use linear way
0115 # to show the histogram in real number, but use a log2 algorithm.
0116 #
0117 
0118 def num2sym(num):
0119         # Each number will have at least one '#'
0120         snum = '#' * (int)(math.log(num, 2) + 1)
0121         return snum
0122 
0123 def show_general_events():
0124 
0125         # Check the total record number in the table
0126         count = con.execute("select count(*) from gen_events")
0127         for t in count:
0128                 print("There is %d records in gen_events table" % t[0])
0129                 if t[0] == 0:
0130                         return
0131 
0132         print("Statistics about the general events grouped by thread/symbol/dso: \n")
0133 
0134          # Group by thread
0135         commq = con.execute("select comm, count(comm) from gen_events group by comm order by -count(comm)")
0136         print("\n%16s %8s %16s\n%s" % ("comm", "number", "histogram", "="*42))
0137         for row in commq:
0138              print("%16s %8d     %s" % (row[0], row[1], num2sym(row[1])))
0139 
0140         # Group by symbol
0141         print("\n%32s %8s %16s\n%s" % ("symbol", "number", "histogram", "="*58))
0142         symbolq = con.execute("select symbol, count(symbol) from gen_events group by symbol order by -count(symbol)")
0143         for row in symbolq:
0144              print("%32s %8d     %s" % (row[0], row[1], num2sym(row[1])))
0145 
0146         # Group by dso
0147         print("\n%40s %8s %16s\n%s" % ("dso", "number", "histogram", "="*74))
0148         dsoq = con.execute("select dso, count(dso) from gen_events group by dso order by -count(dso)")
0149         for row in dsoq:
0150              print("%40s %8d     %s" % (row[0], row[1], num2sym(row[1])))
0151 
0152 #
0153 # This function just shows the basic info, and we could do more with the
0154 # data in the tables, like checking the function parameters when some
0155 # big latency events happen.
0156 #
0157 def show_pebs_ll():
0158 
0159         count = con.execute("select count(*) from pebs_ll")
0160         for t in count:
0161                 print("There is %d records in pebs_ll table" % t[0])
0162                 if t[0] == 0:
0163                         return
0164 
0165         print("Statistics about the PEBS Load Latency events grouped by thread/symbol/dse/latency: \n")
0166 
0167         # Group by thread
0168         commq = con.execute("select comm, count(comm) from pebs_ll group by comm order by -count(comm)")
0169         print("\n%16s %8s %16s\n%s" % ("comm", "number", "histogram", "="*42))
0170         for row in commq:
0171              print("%16s %8d     %s" % (row[0], row[1], num2sym(row[1])))
0172 
0173         # Group by symbol
0174         print("\n%32s %8s %16s\n%s" % ("symbol", "number", "histogram", "="*58))
0175         symbolq = con.execute("select symbol, count(symbol) from pebs_ll group by symbol order by -count(symbol)")
0176         for row in symbolq:
0177              print("%32s %8d     %s" % (row[0], row[1], num2sym(row[1])))
0178 
0179         # Group by dse
0180         dseq = con.execute("select dse, count(dse) from pebs_ll group by dse order by -count(dse)")
0181         print("\n%32s %8s %16s\n%s" % ("dse", "number", "histogram", "="*58))
0182         for row in dseq:
0183              print("%32s %8d     %s" % (row[0], row[1], num2sym(row[1])))
0184 
0185         # Group by latency
0186         latq = con.execute("select lat, count(lat) from pebs_ll group by lat order by lat")
0187         print("\n%32s %8s %16s\n%s" % ("latency", "number", "histogram", "="*58))
0188         for row in latq:
0189              print("%32s %8d     %s" % (row[0], row[1], num2sym(row[1])))
0190 
0191 def trace_unhandled(event_name, context, event_fields_dict):
0192         print (' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())]))