perf tools: Reconstruct event with modifiers from perf_event_attr
Commit-ID: c410431cefefd766266139ed56bca21668e4f9a7 Gitweb: http://git.kernel.org/tip/c410431cefefd766266139ed56bca21668e4f9a7 Author: Arnaldo Carvalho de Melo <[email protected]> AuthorDate: Fri, 25 May 2012 16:38:11 -0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Fri, 25 May 2012 16:38:11 -0300
perf tools: Reconstruct event with modifiers from perf_event_attr
The modifiers:
k kernel space
u user space
h hypervisor
G guest
H host
p, pp, ppp precision level (PEBS)
that can be suffixed to an event were lost when tools used event_name() to reconstruct them from the perf_event_attr entries in a perf.data file.
Fix it by following the defaults used for these modifiers in the current codebase, so:
$ perf record -e instructions:u usleep 1 2> /dev/null $ perf evlist instructions:u $ perf record -e cycles:k usleep 1 2> /dev/null $ perf evlist cycles:k $ perf record -e cycles:kh usleep 1 2> /dev/null $ perf evlist cycles:kh $ perf record -e cache-misses:G usleep 1 2> /dev/null $ perf evlist cache-misses:G $ perf record -e cycles:ppk usleep 1 2> /dev/null $ perf evlist cycles:kpp $
Also works with 'top', 'report', etc.
More work needed to cover tracepoints and software events while not dragging lots of baggage to the python binding, this is a minimal fix for v3.5.
Cc David Ahern <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Mike Galbraith <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Stephane Eranian <[email protected]>
Signed-off-by Arnaldo Carvalho de Melo <[email protected]>
--- tools/perf/util/evsel.c | 90 ++++++++++++++++++++++++++++++++++++++++ tools/perf/util/evsel.h | 3 + tools/perf/util/parse-events.c | 27 +++++------- 3 files changed, 104 insertions(+), 16 deletions(-)
tools/perf/util/evsel.c +90 -0
@@ -15,6 +15,7 @@#include "cpumap.h" #include "thread_map.h" #include "target.h" +#include "../../include/linux/perf_event.h" #define FD (e, x, y) (*(int *)xyarray__entry(e->fd, x, y))#define GROUP_FD (group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0))
@@ -64,6 +65,95 @@ struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx)return evsel; } +static const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX ] = { +"cycles" , +"instructions" , +"cache-references" , +"cache-misses" , +"branches" , +"branch-misses" , +"bus-cycles" , +"stalled-cycles-frontend" , +"stalled-cycles-backend" , +"ref-cycles" , +}; + +const char *__perf_evsel__hw_name (u64 config) +{ +if (config <PERF_COUNT_HW_MAX && perf_evsel__hw_names[config]) +return perf_evsel__hw_names[config]; + +return "unknown-hardware" ; +} + +static int perf_evsel__hw_name (struct perf_evsel *evsel,char *bf,size_t size) +{ +int colon =0 ; +struct perf_event_attr *attr = &evsel->attr; +int r =scnprintf (bf, size,"%s" ,__perf_evsel__hw_name (attr->config)); +bool exclude_guest_default = false; + +#define MOD_PRINT (context, mod) do { \ + if (!attr->exclude_##context) { \ + if (!colon) colon = r++; \ + r += scnprintf(bf + r, size - r, "%c", mod); \ + } } while(0) + +if (attr->exclude_kernel || attr->exclude_user || attr->exclude_hv) { +MOD_PRINT (kernel,'k' ); +MOD_PRINT (user,'u' ); +MOD_PRINT (hv,'h' ); + exclude_guest_default = true; + } + +if (attr->precise_ip) { +if (!colon) + colon = r++; + r +=scnprintf (bf + r, size - r,"%.*s" , attr->precise_ip,"ppp" ); + exclude_guest_default = true; + } + +if (attr->exclude_host || attr->exclude_guest == exclude_guest_default) { +MOD_PRINT (host,'H' ); +MOD_PRINT (guest,'G' ); + } +#undef MOD_PRINT +if (colon) + bf[colon] =':' ; +return r; +} + +int perf_evsel__name (struct perf_evsel *evsel,char *bf,size_t size) +{ +int ret; + +switch (evsel->attr.type) { +case PERF_TYPE_RAW : + ret =scnprintf (bf, size,"raw 0x%" PRIx64, evsel->attr.config); +break ; + +case PERF_TYPE_HARDWARE : + ret =perf_evsel__hw_name (evsel, bf, size); +break ; +default : +/* +* FIXME +* +* This is the minimal perf_evsel__name so that we can +* reconstruct event names taking into account event modifiers. +* +* The old event_name uses it now for raw anr hw events, so that +* we don't drag all the parsing stuff into the python binding. +* +* On the next devel cycle the rest of the event naming will be +* brought here. +*/ +return 0 ; + } + +return ret; +} +void perf_evsel__config (struct perf_evsel *evsel,struct perf_record_opts *opts,struct perf_evsel *first) {
tools/perf/util/evsel.h +3 -0
@@ -83,6 +83,9 @@ void perf_evsel__config(struct perf_evsel *evsel,struct perf_record_opts *opts, struct perf_evsel *first); +const char *__perf_evsel__hw_name (u64 config); +int perf_evsel__name (struct perf_evsel *evsel,char *bf,size_t size); +int perf_evsel__alloc_fd (struct perf_evsel *evsel,int ncpus,int nthreads);int perf_evsel__alloc_id (struct perf_evsel *evsel,int ncpus,int nthreads);int perf_evsel__alloc_counts (struct perf_evsel *evsel,int ncpus);
tools/perf/util/parse-events.c +11 -16
@@ -62,19 +62,6 @@ static struct event_symbol event_symbols[] = {#define PERF_EVENT_TYPE (config) __PERF_EVENT_FIELD(config, TYPE)#define PERF_EVENT_ID (config) __PERF_EVENT_FIELD(config, EVENT) -static const char *hw_event_names[PERF_COUNT_HW_MAX ] = { -"cycles" , -"instructions" , -"cache-references" , -"cache-misses" , -"branches" , -"branch-misses" , -"bus-cycles" , -"stalled-cycles-frontend" , -"stalled-cycles-backend" , -"ref-cycles" , -}; -static const char *sw_event_names[PERF_COUNT_SW_MAX ] = {"cpu-clock" ,"task-clock" ,
@@ -300,6 +287,16 @@ const char *event_name(struct perf_evsel *evsel)u64 config = evsel->attr.config;int type = evsel->attr.type; +if (type ==PERF_TYPE_RAW || type ==PERF_TYPE_HARDWARE ) { +/* +* XXX minimal fix, see comment on perf_evsen__name, this static buffer +* will go away together with event_name in the next devel cycle. +*/ +static char bf[128 ]; +perf_evsel__name (evsel, bf,sizeof (bf)); +return bf; + } +if (evsel->name)return evsel->name;
@@ -317,9 +314,7 @@ const char *__event_name(int type, u64 config)switch (type) {case PERF_TYPE_HARDWARE : -if (config <PERF_COUNT_HW_MAX && hw_event_names[config]) -return hw_event_names[config]; -return "unknown-hardware" ; +return __perf_evsel__hw_name (config);case PERF_TYPE_HW_CACHE : {u8 cache_type, cache_op, cache_result;