perf tools: Enable event_config terms to tracepoint events

This patch enables config terms for tracepoint perf events. Valid terms
for tracepoint events are 'call-graph' and 'stack-size', so we can use
different callgraph settings for each event and eliminate unnecessary
overhead.

Here is an example for using different call-graph config for each
tracepoint.

  $ perf record -e syscalls:sys_enter_write/call-graph=fp/
                -e syscalls:sys_exit_write/call-graph=no/
                dd if=/dev/zero of=test bs=4k count=10

  $ perf report --stdio

  #
  # Total Lost Samples: 0
  #
  # Samples: 13  of event 'syscalls:sys_enter_write'
  # Event count (approx.): 13
  #
  # Children      Self  Command  Shared Object       Symbol
  # ........  ........  .......  ..................  ......................
  #
      76.92%    76.92%  dd       libpthread-2.20.so  [.] __write_nocancel
                   |
                   ---__write_nocancel

      23.08%    23.08%  dd       libc-2.20.so        [.] write
                   |
                   ---write
                      |
                      |--33.33%-- 0x2031342820736574
                      |
                      |--33.33%-- 0xa6e69207364726f
                      |
                       --33.33%-- 0x34202c7320393039
  ...

  # Samples: 13  of event 'syscalls:sys_exit_write'
  # Event count (approx.): 13
  #
  # Children      Self  Command  Shared Object       Symbol
  # ........  ........  .......  ..................  ......................
  #
      76.92%    76.92%  dd       libpthread-2.20.so  [.] __write_nocancel
      23.08%    23.08%  dd       libc-2.20.so        [.] write
       7.69%     0.00%  dd       [unknown]           [.] 0x0a6e69207364726f
       7.69%     0.00%  dd       [unknown]           [.] 0x2031342820736574
       7.69%     0.00%  dd       [unknown]           [.] 0x34202c7320393039

Signed-off-by: He Kuang <hekuang@huawei.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Kan Liang <kan.liang@intel.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Wang Nan <wangnan0@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/1443412336-120050-4-git-send-email-hekuang@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
He Kuang 2015-09-28 03:52:16 +00:00 committed by Arnaldo Carvalho de Melo
parent 865582c3f4
commit e637d17757
3 changed files with 90 additions and 23 deletions

View File

@ -27,6 +27,8 @@
extern int parse_events_debug; extern int parse_events_debug;
#endif #endif
int parse_events_parse(void *data, void *scanner); int parse_events_parse(void *data, void *scanner);
static int get_config_terms(struct list_head *head_config,
struct list_head *head_terms __maybe_unused);
static struct perf_pmu_event_symbol *perf_pmu_events_list; static struct perf_pmu_event_symbol *perf_pmu_events_list;
/* /*
@ -416,7 +418,8 @@ static void tracepoint_error(struct parse_events_error *error, int err,
static int add_tracepoint(struct list_head *list, int *idx, static int add_tracepoint(struct list_head *list, int *idx,
char *sys_name, char *evt_name, char *sys_name, char *evt_name,
struct parse_events_error *error __maybe_unused) struct parse_events_error *error __maybe_unused,
struct list_head *head_config)
{ {
struct perf_evsel *evsel; struct perf_evsel *evsel;
@ -426,13 +429,22 @@ static int add_tracepoint(struct list_head *list, int *idx,
return PTR_ERR(evsel); return PTR_ERR(evsel);
} }
if (head_config) {
LIST_HEAD(config_terms);
if (get_config_terms(head_config, &config_terms))
return -ENOMEM;
list_splice(&config_terms, &evsel->config_terms);
}
list_add_tail(&evsel->node, list); list_add_tail(&evsel->node, list);
return 0; return 0;
} }
static int add_tracepoint_multi_event(struct list_head *list, int *idx, static int add_tracepoint_multi_event(struct list_head *list, int *idx,
char *sys_name, char *evt_name, char *sys_name, char *evt_name,
struct parse_events_error *error) struct parse_events_error *error,
struct list_head *head_config)
{ {
char evt_path[MAXPATHLEN]; char evt_path[MAXPATHLEN];
struct dirent *evt_ent; struct dirent *evt_ent;
@ -456,7 +468,8 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx,
if (!strglobmatch(evt_ent->d_name, evt_name)) if (!strglobmatch(evt_ent->d_name, evt_name))
continue; continue;
ret = add_tracepoint(list, idx, sys_name, evt_ent->d_name, error); ret = add_tracepoint(list, idx, sys_name, evt_ent->d_name,
error, head_config);
} }
closedir(evt_dir); closedir(evt_dir);
@ -465,16 +478,20 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx,
static int add_tracepoint_event(struct list_head *list, int *idx, static int add_tracepoint_event(struct list_head *list, int *idx,
char *sys_name, char *evt_name, char *sys_name, char *evt_name,
struct parse_events_error *error) struct parse_events_error *error,
struct list_head *head_config)
{ {
return strpbrk(evt_name, "*?") ? return strpbrk(evt_name, "*?") ?
add_tracepoint_multi_event(list, idx, sys_name, evt_name, error) : add_tracepoint_multi_event(list, idx, sys_name, evt_name,
add_tracepoint(list, idx, sys_name, evt_name, error); error, head_config) :
add_tracepoint(list, idx, sys_name, evt_name,
error, head_config);
} }
static int add_tracepoint_multi_sys(struct list_head *list, int *idx, static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
char *sys_name, char *evt_name, char *sys_name, char *evt_name,
struct parse_events_error *error) struct parse_events_error *error,
struct list_head *head_config)
{ {
struct dirent *events_ent; struct dirent *events_ent;
DIR *events_dir; DIR *events_dir;
@ -498,23 +515,13 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
continue; continue;
ret = add_tracepoint_event(list, idx, events_ent->d_name, ret = add_tracepoint_event(list, idx, events_ent->d_name,
evt_name, error); evt_name, error, head_config);
} }
closedir(events_dir); closedir(events_dir);
return ret; return ret;
} }
int parse_events_add_tracepoint(struct list_head *list, int *idx,
char *sys, char *event,
struct parse_events_error *error)
{
if (strpbrk(sys, "*?"))
return add_tracepoint_multi_sys(list, idx, sys, event, error);
else
return add_tracepoint_event(list, idx, sys, event, error);
}
static int static int
parse_breakpoint_type(const char *type, struct perf_event_attr *attr) parse_breakpoint_type(const char *type, struct perf_event_attr *attr)
{ {
@ -680,6 +687,26 @@ static int config_term_pmu(struct perf_event_attr *attr,
return config_term_common(attr, term, err); return config_term_common(attr, term, err);
} }
static int config_term_tracepoint(struct perf_event_attr *attr,
struct parse_events_term *term,
struct parse_events_error *err)
{
switch (term->type_term) {
case PARSE_EVENTS__TERM_TYPE_CALLGRAPH:
case PARSE_EVENTS__TERM_TYPE_STACKSIZE:
return config_term_common(attr, term, err);
default:
if (err) {
err->idx = term->err_term;
err->str = strdup("unknown term");
err->help = strdup("valid terms: call-graph,stack-size\n");
}
return -EINVAL;
}
return 0;
}
static int config_attr(struct perf_event_attr *attr, static int config_attr(struct perf_event_attr *attr,
struct list_head *head, struct list_head *head,
struct parse_events_error *err, struct parse_events_error *err,
@ -738,6 +765,27 @@ do { \
return 0; return 0;
} }
int parse_events_add_tracepoint(struct list_head *list, int *idx,
char *sys, char *event,
struct parse_events_error *error,
struct list_head *head_config)
{
if (head_config) {
struct perf_event_attr attr;
if (config_attr(&attr, head_config, error,
config_term_tracepoint))
return -EINVAL;
}
if (strpbrk(sys, "*?"))
return add_tracepoint_multi_sys(list, idx, sys, event,
error, head_config);
else
return add_tracepoint_event(list, idx, sys, event,
error, head_config);
}
int parse_events_add_numeric(struct parse_events_evlist *data, int parse_events_add_numeric(struct parse_events_evlist *data,
struct list_head *list, struct list_head *list,
u32 type, u64 config, u32 type, u64 config,

View File

@ -119,7 +119,8 @@ int parse_events__modifier_group(struct list_head *list, char *event_mod);
int parse_events_name(struct list_head *list, char *name); int parse_events_name(struct list_head *list, char *name);
int parse_events_add_tracepoint(struct list_head *list, int *idx, int parse_events_add_tracepoint(struct list_head *list, int *idx,
char *sys, char *event, char *sys, char *event,
struct parse_events_error *error); struct parse_events_error *error,
struct list_head *head_config);
int parse_events_add_numeric(struct parse_events_evlist *data, int parse_events_add_numeric(struct parse_events_evlist *data,
struct list_head *list, struct list_head *list,
u32 type, u64 config, u32 type, u64 config,

View File

@ -380,12 +380,30 @@ tracepoint_name
struct list_head *list; struct list_head *list;
ALLOC_LIST(list); ALLOC_LIST(list);
if (parse_events_add_tracepoint(list, &data->idx, $1.sys, $1.event,
error)) {
if (error) if (error)
error->idx = @1.first_column; error->idx = @1.first_column;
if (parse_events_add_tracepoint(list, &data->idx, $1.sys, $1.event,
error, NULL))
return -1; return -1;
}
$$ = list;
}
|
tracepoint_name '/' event_config '/'
{
struct parse_events_evlist *data = _data;
struct parse_events_error *error = data->error;
struct list_head *list;
ALLOC_LIST(list);
if (error)
error->idx = @1.first_column;
if (parse_events_add_tracepoint(list, &data->idx, $1.sys, $1.event,
error, $3))
return -1;
$$ = list; $$ = list;
} }