Skip to content

Commit

Permalink
perf callchain: Per-event type selection support
Browse files Browse the repository at this point in the history
This patchkit adds the ability to set callgraph mode (fp, dwarf, lbr) per
event. This in term can reduce sampling overhead and the size of the
perf.data.

Here is an example.

  perf record -e 'cpu/cpu-cycles,period=1000,call-graph=fp,time=1/,cpu/instructions,call-graph=lbr/' sleep 1

 perf evlist -v
 cpu/cpu-cycles,period=1000,call-graph=fp,time=1/: type: 4, size: 112,
 config: 0x3c, { sample_period, sample_freq }: 1000, sample_type:
 IP|TID|TIME|CALLCHAIN|PERIOD|IDENTIFIER, read_format: ID, disabled: 1,
 inherit: 1, mmap: 1, comm: 1, enable_on_exec: 1, task: 1, sample_id_all:
 1, exclude_guest: 1, mmap2: 1, comm_exec: 1
 cpu/instructions,call-graph=lbr/: type: 4, size: 112, config: 0xc0, {
 sample_period, sample_freq }: 4000, sample_type:
 IP|TID|TIME|CALLCHAIN|PERIOD|BRANCH_STACK|IDENTIFIER, read_format: ID,
 disabled: 1, inherit: 1, freq: 1, enable_on_exec: 1, sample_id_all: 1,
 exclude_guest: 1

Signed-off-by: Kan Liang <kan.liang@intel.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Link: http://lkml.kernel.org/r/1439289050-40510-1-git-send-email-kan.liang@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
  • Loading branch information
Kan Liang authored and Arnaldo Carvalho de Melo committed Aug 12, 2015
1 parent 75186a9 commit d457c96
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 3 deletions.
3 changes: 3 additions & 0 deletions tools/perf/Documentation/perf-record.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ OPTIONS
- 'time': Disable/enable time stamping. Acceptable values are 1 for
enabling time stamping. 0 for disabling time stamping.
The default is 1.
- 'call-graph': Disable/enable callgraph. Acceptable str are "fp" for
FP mode, "dwarf" for DWARF mode, "lbr" for LBR mode.
- 'stack-size': user stack size for dwarf mode
Note: If user explicitly sets options which conflict with the params,
the value set by the params will be overridden.

Expand Down
62 changes: 60 additions & 2 deletions tools/perf/util/evsel.c
Original file line number Diff line number Diff line change
Expand Up @@ -588,11 +588,36 @@ perf_evsel__config_callgraph(struct perf_evsel *evsel,
}
}

static void apply_config_terms(struct perf_evsel *evsel)
static void
perf_evsel__reset_callgraph(struct perf_evsel *evsel,
struct callchain_param *param)
{
struct perf_event_attr *attr = &evsel->attr;

perf_evsel__reset_sample_bit(evsel, CALLCHAIN);
if (param->record_mode == CALLCHAIN_LBR) {
perf_evsel__reset_sample_bit(evsel, BRANCH_STACK);
attr->branch_sample_type &= ~(PERF_SAMPLE_BRANCH_USER |
PERF_SAMPLE_BRANCH_CALL_STACK);
}
if (param->record_mode == CALLCHAIN_DWARF) {
perf_evsel__reset_sample_bit(evsel, REGS_USER);
perf_evsel__reset_sample_bit(evsel, STACK_USER);
}
}

static void apply_config_terms(struct perf_evsel *evsel,
struct record_opts *opts)
{
struct perf_evsel_config_term *term;
struct list_head *config_terms = &evsel->config_terms;
struct perf_event_attr *attr = &evsel->attr;
struct callchain_param param;
u32 dump_size = 0;
char *callgraph_buf = NULL;

/* callgraph default */
param.record_mode = callchain_param.record_mode;

list_for_each_entry(term, config_terms, list) {
switch (term->type) {
Expand All @@ -610,10 +635,43 @@ static void apply_config_terms(struct perf_evsel *evsel)
else
perf_evsel__reset_sample_bit(evsel, TIME);
break;
case PERF_EVSEL__CONFIG_TERM_CALLGRAPH:
callgraph_buf = term->val.callgraph;
break;
case PERF_EVSEL__CONFIG_TERM_STACK_USER:
dump_size = term->val.stack_user;
break;
default:
break;
}
}

/* User explicitly set per-event callgraph, clear the old setting and reset. */
if ((callgraph_buf != NULL) || (dump_size > 0)) {

/* parse callgraph parameters */
if (callgraph_buf != NULL) {
param.enabled = true;
if (parse_callchain_record(callgraph_buf, &param)) {
pr_err("per-event callgraph setting for %s failed. "
"Apply callgraph global setting for it\n",
evsel->name);
return;
}
}
if (dump_size > 0) {
dump_size = round_up(dump_size, sizeof(u64));
param.dump_size = dump_size;
}

/* If global callgraph set, clear it */
if (callchain_param.enabled)
perf_evsel__reset_callgraph(evsel, &callchain_param);

/* set perf-event callgraph */
if (param.enabled)
perf_evsel__config_callgraph(evsel, opts, &param);
}
}

/*
Expand Down Expand Up @@ -812,7 +870,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
* Apply event specific term settings,
* it overloads any global configuration.
*/
apply_config_terms(evsel);
apply_config_terms(evsel, opts);
}

static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
Expand Down
4 changes: 4 additions & 0 deletions tools/perf/util/evsel.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ enum {
PERF_EVSEL__CONFIG_TERM_PERIOD,
PERF_EVSEL__CONFIG_TERM_FREQ,
PERF_EVSEL__CONFIG_TERM_TIME,
PERF_EVSEL__CONFIG_TERM_CALLGRAPH,
PERF_EVSEL__CONFIG_TERM_STACK_USER,
PERF_EVSEL__CONFIG_TERM_MAX,
};

Expand All @@ -51,6 +53,8 @@ struct perf_evsel_config_term {
u64 period;
u64 freq;
bool time;
char *callgraph;
u64 stack_user;
} val;
};

Expand Down
12 changes: 12 additions & 0 deletions tools/perf/util/parse-events.c
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,12 @@ do { \
return -EINVAL;
}
break;
case PARSE_EVENTS__TERM_TYPE_CALLGRAPH:
CHECK_TYPE_VAL(STR);
break;
case PARSE_EVENTS__TERM_TYPE_STACKSIZE:
CHECK_TYPE_VAL(NUM);
break;
case PARSE_EVENTS__TERM_TYPE_NAME:
CHECK_TYPE_VAL(STR);
break;
Expand Down Expand Up @@ -668,6 +674,12 @@ do { \
case PARSE_EVENTS__TERM_TYPE_TIME:
ADD_CONFIG_TERM(TIME, time, term->val.num);
break;
case PARSE_EVENTS__TERM_TYPE_CALLGRAPH:
ADD_CONFIG_TERM(CALLGRAPH, callgraph, term->val.str);
break;
case PARSE_EVENTS__TERM_TYPE_STACKSIZE:
ADD_CONFIG_TERM(STACK_USER, stack_user, term->val.num);
break;
default:
break;
}
Expand Down
2 changes: 2 additions & 0 deletions tools/perf/util/parse-events.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ enum {
PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ,
PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE,
PARSE_EVENTS__TERM_TYPE_TIME,
PARSE_EVENTS__TERM_TYPE_CALLGRAPH,
PARSE_EVENTS__TERM_TYPE_STACKSIZE,
};

struct parse_events_term {
Expand Down
2 changes: 2 additions & 0 deletions tools/perf/util/parse-events.l
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ period { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); }
freq { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ); }
branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); }
time { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_TIME); }
call-graph { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CALLGRAPH); }
stack-size { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_STACKSIZE); }
, { return ','; }
"/" { BEGIN(INITIAL); return '/'; }
{name_minus} { return str(yyscanner, PE_NAME); }
Expand Down
4 changes: 3 additions & 1 deletion tools/perf/util/pmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -634,7 +634,9 @@ static char *formats_error_string(struct list_head *formats)
{
struct perf_pmu_format *format;
char *err, *str;
static const char *static_terms = "config,config1,config2,name,period,freq,branch_type,time\n";
static const char *static_terms = "config,config1,config2,name,"
"period,freq,branch_type,time,"
"call-graph,stack-size\n";
unsigned i = 0;

if (!asprintf(&str, "valid terms:"))
Expand Down

0 comments on commit d457c96

Please sign in to comment.