perf callchain: Per-event type selection support
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>
This commit is contained in:

committed by
Arnaldo Carvalho de Melo

parent
75186a9b09
commit
d457c96392
@@ -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) {
|
||||
@@ -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, ¶m)) {
|
||||
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, ¶m);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -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)
|
||||
|
Reference in New Issue
Block a user