diff options
| author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-10-17 16:32:49 +0400 | 
|---|---|---|
| committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-10-17 16:32:49 +0400 | 
| commit | 214e2ca2b82d335935a861c253fe94c61ad77aad (patch) | |
| tree | eee42ff74d10470789d919b8499737ad0e919360 /tools/perf/scripts/python | |
| parent | 1fdead8ad31d3aa833bc37739273fcde89ace93c (diff) | |
| parent | ddffeb8c4d0331609ef2581d84de4d763607bd37 (diff) | |
| download | linux-214e2ca2b82d335935a861c253fe94c61ad77aad.tar.xz | |
Merge tag 'v3.7-rc1' into staging/for_v3.8
Linux 3.7-rc1
* tag 'v3.7-rc1': (9579 commits)
  Linux 3.7-rc1
  x86, boot: Explicitly include autoconf.h for hostprogs
  perf: Fix UAPI fallout
  ARM: config: make sure that platforms are ordered by option string
  ARM: config: sort select statements alphanumerically
  UAPI: (Scripted) Disintegrate include/linux/byteorder
  UAPI: (Scripted) Disintegrate include/linux
  UAPI: Unexport linux/blk_types.h
  UAPI: Unexport part of linux/ppp-comp.h
  perf: Handle new rbtree implementation
  procfs: don't need a PATH_MAX allocation to hold a string representation of an int
  vfs: embed struct filename inside of names_cache allocation if possible
  audit: make audit_inode take struct filename
  vfs: make path_openat take a struct filename pointer
  vfs: turn do_path_lookup into wrapper around struct filename variant
  audit: allow audit code to satisfy getname requests from its names_list
  vfs: define struct filename and have getname() return it
  btrfs: Fix compilation with user namespace support enabled
  userns: Fix posix_acl_file_xattr_userns gid conversion
  userns: Properly print bluetooth socket uids
  ...
Diffstat (limited to 'tools/perf/scripts/python')
4 files changed, 294 insertions, 0 deletions
| diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/EventClass.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/EventClass.py new file mode 100755 index 000000000000..9e0985794e20 --- /dev/null +++ b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/EventClass.py @@ -0,0 +1,94 @@ +# EventClass.py +# +# This is a library defining some events types classes, which could +# be used by other scripts to analyzing the perf samples. +# +# Currently there are just a few classes defined for examples, +# PerfEvent is the base class for all perf event sample, PebsEvent +# is a HW base Intel x86 PEBS event, and user could add more SW/HW +# event classes based on requirements. + +import struct + +# Event types, user could add more here +EVTYPE_GENERIC  = 0 +EVTYPE_PEBS     = 1     # Basic PEBS event +EVTYPE_PEBS_LL  = 2     # PEBS event with load latency info +EVTYPE_IBS      = 3 + +# +# Currently we don't have good way to tell the event type, but by +# the size of raw buffer, raw PEBS event with load latency data's +# size is 176 bytes, while the pure PEBS event's size is 144 bytes. +# +def create_event(name, comm, dso, symbol, raw_buf): +        if (len(raw_buf) == 144): +                event = PebsEvent(name, comm, dso, symbol, raw_buf) +        elif (len(raw_buf) == 176): +                event = PebsNHM(name, comm, dso, symbol, raw_buf) +        else: +                event = PerfEvent(name, comm, dso, symbol, raw_buf) + +        return event + +class PerfEvent(object): +        event_num = 0 +        def __init__(self, name, comm, dso, symbol, raw_buf, ev_type=EVTYPE_GENERIC): +                self.name       = name +                self.comm       = comm +                self.dso        = dso +                self.symbol     = symbol +                self.raw_buf    = raw_buf +                self.ev_type    = ev_type +                PerfEvent.event_num += 1 + +        def show(self): +                print "PMU event: name=%12s, symbol=%24s, comm=%8s, dso=%12s" % (self.name, self.symbol, self.comm, self.dso) + +# +# Basic Intel PEBS (Precise Event-based Sampling) event, whose raw buffer +# contains the context info when that event happened: the EFLAGS and +# linear IP info, as well as all the registers. +# +class PebsEvent(PerfEvent): +        pebs_num = 0 +        def __init__(self, name, comm, dso, symbol, raw_buf, ev_type=EVTYPE_PEBS): +                tmp_buf=raw_buf[0:80] +                flags, ip, ax, bx, cx, dx, si, di, bp, sp = struct.unpack('QQQQQQQQQQ', tmp_buf) +                self.flags = flags +                self.ip    = ip +                self.ax    = ax +                self.bx    = bx +                self.cx    = cx +                self.dx    = dx +                self.si    = si +                self.di    = di +                self.bp    = bp +                self.sp    = sp + +                PerfEvent.__init__(self, name, comm, dso, symbol, raw_buf, ev_type) +                PebsEvent.pebs_num += 1 +                del tmp_buf + +# +# Intel Nehalem and Westmere support PEBS plus Load Latency info which lie +# in the four 64 bit words write after the PEBS data: +#       Status: records the IA32_PERF_GLOBAL_STATUS register value +#       DLA:    Data Linear Address (EIP) +#       DSE:    Data Source Encoding, where the latency happens, hit or miss +#               in L1/L2/L3 or IO operations +#       LAT:    the actual latency in cycles +# +class PebsNHM(PebsEvent): +        pebs_nhm_num = 0 +        def __init__(self, name, comm, dso, symbol, raw_buf, ev_type=EVTYPE_PEBS_LL): +                tmp_buf=raw_buf[144:176] +                status, dla, dse, lat = struct.unpack('QQQQ', tmp_buf) +                self.status = status +                self.dla = dla +                self.dse = dse +                self.lat = lat + +                PebsEvent.__init__(self, name, comm, dso, symbol, raw_buf, ev_type) +                PebsNHM.pebs_nhm_num += 1 +                del tmp_buf diff --git a/tools/perf/scripts/python/bin/event_analyzing_sample-record b/tools/perf/scripts/python/bin/event_analyzing_sample-record new file mode 100644 index 000000000000..5ce652dabd02 --- /dev/null +++ b/tools/perf/scripts/python/bin/event_analyzing_sample-record @@ -0,0 +1,8 @@ +#!/bin/bash + +# +# event_analyzing_sample.py can cover all type of perf samples including +# the tracepoints, so no special record requirements, just record what +# you want to analyze. +# +perf record $@ diff --git a/tools/perf/scripts/python/bin/event_analyzing_sample-report b/tools/perf/scripts/python/bin/event_analyzing_sample-report new file mode 100644 index 000000000000..0941fc94e158 --- /dev/null +++ b/tools/perf/scripts/python/bin/event_analyzing_sample-report @@ -0,0 +1,3 @@ +#!/bin/bash +# description: analyze all perf samples +perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/event_analyzing_sample.py diff --git a/tools/perf/scripts/python/event_analyzing_sample.py b/tools/perf/scripts/python/event_analyzing_sample.py new file mode 100644 index 000000000000..163c39fa12d9 --- /dev/null +++ b/tools/perf/scripts/python/event_analyzing_sample.py @@ -0,0 +1,189 @@ +# event_analyzing_sample.py: general event handler in python +# +# Current perf report is already very powerful with the annotation integrated, +# and this script is not trying to be as powerful as perf report, but +# providing end user/developer a flexible way to analyze the events other +# than trace points. +# +# The 2 database related functions in this script just show how to gather +# the basic information, and users can modify and write their own functions +# according to their specific requirement. +# +# The first function "show_general_events" just does a basic grouping for all +# generic events with the help of sqlite, and the 2nd one "show_pebs_ll" is +# for a x86 HW PMU event: PEBS with load latency data. +# + +import os +import sys +import math +import struct +import sqlite3 + +sys.path.append(os.environ['PERF_EXEC_PATH'] + \ +        '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') + +from perf_trace_context import * +from EventClass import * + +# +# If the perf.data has a big number of samples, then the insert operation +# will be very time consuming (about 10+ minutes for 10000 samples) if the +# .db database is on disk. Move the .db file to RAM based FS to speedup +# the handling, which will cut the time down to several seconds. +# +con = sqlite3.connect("/dev/shm/perf.db") +con.isolation_level = None + +def trace_begin(): +	print "In trace_begin:\n" + +        # +        # Will create several tables at the start, pebs_ll is for PEBS data with +        # load latency info, while gen_events is for general event. +        # +        con.execute(""" +                create table if not exists gen_events ( +                        name text, +                        symbol text, +                        comm text, +                        dso text +                );""") +        con.execute(""" +                create table if not exists pebs_ll ( +                        name text, +                        symbol text, +                        comm text, +                        dso text, +                        flags integer, +                        ip integer, +                        status integer, +                        dse integer, +                        dla integer, +                        lat integer +                );""") + +# +# Create and insert event object to a database so that user could +# do more analysis with simple database commands. +# +def process_event(param_dict): +        event_attr = param_dict["attr"] +        sample     = param_dict["sample"] +        raw_buf    = param_dict["raw_buf"] +        comm       = param_dict["comm"] +        name       = param_dict["ev_name"] + +        # Symbol and dso info are not always resolved +        if (param_dict.has_key("dso")): +                dso = param_dict["dso"] +        else: +                dso = "Unknown_dso" + +        if (param_dict.has_key("symbol")): +                symbol = param_dict["symbol"] +        else: +                symbol = "Unknown_symbol" + +        # Create the event object and insert it to the right table in database +        event = create_event(name, comm, dso, symbol, raw_buf) +        insert_db(event) + +def insert_db(event): +        if event.ev_type == EVTYPE_GENERIC: +                con.execute("insert into gen_events values(?, ?, ?, ?)", +                                (event.name, event.symbol, event.comm, event.dso)) +        elif event.ev_type == EVTYPE_PEBS_LL: +                event.ip &= 0x7fffffffffffffff +                event.dla &= 0x7fffffffffffffff +                con.execute("insert into pebs_ll values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", +                        (event.name, event.symbol, event.comm, event.dso, event.flags, +                                event.ip, event.status, event.dse, event.dla, event.lat)) + +def trace_end(): +	print "In trace_end:\n" +        # We show the basic info for the 2 type of event classes +        show_general_events() +        show_pebs_ll() +        con.close() + +# +# As the event number may be very big, so we can't use linear way +# to show the histogram in real number, but use a log2 algorithm. +# + +def num2sym(num): +        # Each number will have at least one '#' +        snum = '#' * (int)(math.log(num, 2) + 1) +        return snum + +def show_general_events(): + +        # Check the total record number in the table +        count = con.execute("select count(*) from gen_events") +        for t in count: +                print "There is %d records in gen_events table" % t[0] +                if t[0] == 0: +                        return + +        print "Statistics about the general events grouped by thread/symbol/dso: \n" + +         # Group by thread +        commq = con.execute("select comm, count(comm) from gen_events group by comm order by -count(comm)") +        print "\n%16s %8s %16s\n%s" % ("comm", "number", "histogram", "="*42) +        for row in commq: +             print "%16s %8d     %s" % (row[0], row[1], num2sym(row[1])) + +        # Group by symbol +        print "\n%32s %8s %16s\n%s" % ("symbol", "number", "histogram", "="*58) +        symbolq = con.execute("select symbol, count(symbol) from gen_events group by symbol order by -count(symbol)") +        for row in symbolq: +             print "%32s %8d     %s" % (row[0], row[1], num2sym(row[1])) + +        # Group by dso +        print "\n%40s %8s %16s\n%s" % ("dso", "number", "histogram", "="*74) +        dsoq = con.execute("select dso, count(dso) from gen_events group by dso order by -count(dso)") +        for row in dsoq: +             print "%40s %8d     %s" % (row[0], row[1], num2sym(row[1])) + +# +# This function just shows the basic info, and we could do more with the +# data in the tables, like checking the function parameters when some +# big latency events happen. +# +def show_pebs_ll(): + +        count = con.execute("select count(*) from pebs_ll") +        for t in count: +                print "There is %d records in pebs_ll table" % t[0] +                if t[0] == 0: +                        return + +        print "Statistics about the PEBS Load Latency events grouped by thread/symbol/dse/latency: \n" + +        # Group by thread +        commq = con.execute("select comm, count(comm) from pebs_ll group by comm order by -count(comm)") +        print "\n%16s %8s %16s\n%s" % ("comm", "number", "histogram", "="*42) +        for row in commq: +             print "%16s %8d     %s" % (row[0], row[1], num2sym(row[1])) + +        # Group by symbol +        print "\n%32s %8s %16s\n%s" % ("symbol", "number", "histogram", "="*58) +        symbolq = con.execute("select symbol, count(symbol) from pebs_ll group by symbol order by -count(symbol)") +        for row in symbolq: +             print "%32s %8d     %s" % (row[0], row[1], num2sym(row[1])) + +        # Group by dse +        dseq = con.execute("select dse, count(dse) from pebs_ll group by dse order by -count(dse)") +        print "\n%32s %8s %16s\n%s" % ("dse", "number", "histogram", "="*58) +        for row in dseq: +             print "%32s %8d     %s" % (row[0], row[1], num2sym(row[1])) + +        # Group by latency +        latq = con.execute("select lat, count(lat) from pebs_ll group by lat order by lat") +        print "\n%32s %8s %16s\n%s" % ("latency", "number", "histogram", "="*58) +        for row in latq: +             print "%32s %8d     %s" % (row[0], row[1], num2sym(row[1])) + +def trace_unhandled(event_name, context, event_fields_dict): +		print ' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())]) | 
