aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorKan Liang <kan.liang@intel.com>2015-08-11 06:30:47 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2015-08-12 12:20:27 -0400
commitd457c96392bb418bd998f3ccf93e0e4c958fcd0f (patch)
tree39588c97ab0c7250fdfc9e85be87519cd82d2332 /tools/perf
parent75186a9b09e47072f442f43e292cd47180b67b5c (diff)
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>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Documentation/perf-record.txt3
-rw-r--r--tools/perf/util/evsel.c62
-rw-r--r--tools/perf/util/evsel.h4
-rw-r--r--tools/perf/util/parse-events.c12
-rw-r--r--tools/perf/util/parse-events.h2
-rw-r--r--tools/perf/util/parse-events.l2
-rw-r--r--tools/perf/util/pmu.c4
7 files changed, 86 insertions, 3 deletions
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index afbe45ef7e3e..7f82dec2b541 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -53,6 +53,9 @@ OPTIONS
53 - 'time': Disable/enable time stamping. Acceptable values are 1 for 53 - 'time': Disable/enable time stamping. Acceptable values are 1 for
54 enabling time stamping. 0 for disabling time stamping. 54 enabling time stamping. 0 for disabling time stamping.
55 The default is 1. 55 The default is 1.
56 - 'call-graph': Disable/enable callgraph. Acceptable str are "fp" for
57 FP mode, "dwarf" for DWARF mode, "lbr" for LBR mode.
58 - 'stack-size': user stack size for dwarf mode
56 Note: If user explicitly sets options which conflict with the params, 59 Note: If user explicitly sets options which conflict with the params,
57 the value set by the params will be overridden. 60 the value set by the params will be overridden.
58 61
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 04fddddc6b6f..6647925d5f28 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -588,11 +588,36 @@ perf_evsel__config_callgraph(struct perf_evsel *evsel,
588 } 588 }
589} 589}
590 590
591static void apply_config_terms(struct perf_evsel *evsel) 591static void
592perf_evsel__reset_callgraph(struct perf_evsel *evsel,
593 struct callchain_param *param)
594{
595 struct perf_event_attr *attr = &evsel->attr;
596
597 perf_evsel__reset_sample_bit(evsel, CALLCHAIN);
598 if (param->record_mode == CALLCHAIN_LBR) {
599 perf_evsel__reset_sample_bit(evsel, BRANCH_STACK);
600 attr->branch_sample_type &= ~(PERF_SAMPLE_BRANCH_USER |
601 PERF_SAMPLE_BRANCH_CALL_STACK);
602 }
603 if (param->record_mode == CALLCHAIN_DWARF) {
604 perf_evsel__reset_sample_bit(evsel, REGS_USER);
605 perf_evsel__reset_sample_bit(evsel, STACK_USER);
606 }
607}
608
609static void apply_config_terms(struct perf_evsel *evsel,
610 struct record_opts *opts)
592{ 611{
593 struct perf_evsel_config_term *term; 612 struct perf_evsel_config_term *term;
594 struct list_head *config_terms = &evsel->config_terms; 613 struct list_head *config_terms = &evsel->config_terms;
595 struct perf_event_attr *attr = &evsel->attr; 614 struct perf_event_attr *attr = &evsel->attr;
615 struct callchain_param param;
616 u32 dump_size = 0;
617 char *callgraph_buf = NULL;
618
619 /* callgraph default */
620 param.record_mode = callchain_param.record_mode;
596 621
597 list_for_each_entry(term, config_terms, list) { 622 list_for_each_entry(term, config_terms, list) {
598 switch (term->type) { 623 switch (term->type) {
@@ -610,10 +635,43 @@ static void apply_config_terms(struct perf_evsel *evsel)
610 else 635 else
611 perf_evsel__reset_sample_bit(evsel, TIME); 636 perf_evsel__reset_sample_bit(evsel, TIME);
612 break; 637 break;
638 case PERF_EVSEL__CONFIG_TERM_CALLGRAPH:
639 callgraph_buf = term->val.callgraph;
640 break;
641 case PERF_EVSEL__CONFIG_TERM_STACK_USER:
642 dump_size = term->val.stack_user;
643 break;
613 default: 644 default:
614 break; 645 break;
615 } 646 }
616 } 647 }
648
649 /* User explicitly set per-event callgraph, clear the old setting and reset. */
650 if ((callgraph_buf != NULL) || (dump_size > 0)) {
651
652 /* parse callgraph parameters */
653 if (callgraph_buf != NULL) {
654 param.enabled = true;
655 if (parse_callchain_record(callgraph_buf, &param)) {
656 pr_err("per-event callgraph setting for %s failed. "
657 "Apply callgraph global setting for it\n",
658 evsel->name);
659 return;
660 }
661 }
662 if (dump_size > 0) {
663 dump_size = round_up(dump_size, sizeof(u64));
664 param.dump_size = dump_size;
665 }
666
667 /* If global callgraph set, clear it */
668 if (callchain_param.enabled)
669 perf_evsel__reset_callgraph(evsel, &callchain_param);
670
671 /* set perf-event callgraph */
672 if (param.enabled)
673 perf_evsel__config_callgraph(evsel, opts, &param);
674 }
617} 675}
618 676
619/* 677/*
@@ -812,7 +870,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
812 * Apply event specific term settings, 870 * Apply event specific term settings,
813 * it overloads any global configuration. 871 * it overloads any global configuration.
814 */ 872 */
815 apply_config_terms(evsel); 873 apply_config_terms(evsel, opts);
816} 874}
817 875
818static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) 876static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index fdf2674ab339..93ac6b128149 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -41,6 +41,8 @@ enum {
41 PERF_EVSEL__CONFIG_TERM_PERIOD, 41 PERF_EVSEL__CONFIG_TERM_PERIOD,
42 PERF_EVSEL__CONFIG_TERM_FREQ, 42 PERF_EVSEL__CONFIG_TERM_FREQ,
43 PERF_EVSEL__CONFIG_TERM_TIME, 43 PERF_EVSEL__CONFIG_TERM_TIME,
44 PERF_EVSEL__CONFIG_TERM_CALLGRAPH,
45 PERF_EVSEL__CONFIG_TERM_STACK_USER,
44 PERF_EVSEL__CONFIG_TERM_MAX, 46 PERF_EVSEL__CONFIG_TERM_MAX,
45}; 47};
46 48
@@ -51,6 +53,8 @@ struct perf_evsel_config_term {
51 u64 period; 53 u64 period;
52 u64 freq; 54 u64 freq;
53 bool time; 55 bool time;
56 char *callgraph;
57 u64 stack_user;
54 } val; 58 } val;
55}; 59};
56 60
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index dbf315df4220..d826e6f515db 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -614,6 +614,12 @@ do { \
614 return -EINVAL; 614 return -EINVAL;
615 } 615 }
616 break; 616 break;
617 case PARSE_EVENTS__TERM_TYPE_CALLGRAPH:
618 CHECK_TYPE_VAL(STR);
619 break;
620 case PARSE_EVENTS__TERM_TYPE_STACKSIZE:
621 CHECK_TYPE_VAL(NUM);
622 break;
617 case PARSE_EVENTS__TERM_TYPE_NAME: 623 case PARSE_EVENTS__TERM_TYPE_NAME:
618 CHECK_TYPE_VAL(STR); 624 CHECK_TYPE_VAL(STR);
619 break; 625 break;
@@ -668,6 +674,12 @@ do { \
668 case PARSE_EVENTS__TERM_TYPE_TIME: 674 case PARSE_EVENTS__TERM_TYPE_TIME:
669 ADD_CONFIG_TERM(TIME, time, term->val.num); 675 ADD_CONFIG_TERM(TIME, time, term->val.num);
670 break; 676 break;
677 case PARSE_EVENTS__TERM_TYPE_CALLGRAPH:
678 ADD_CONFIG_TERM(CALLGRAPH, callgraph, term->val.str);
679 break;
680 case PARSE_EVENTS__TERM_TYPE_STACKSIZE:
681 ADD_CONFIG_TERM(STACK_USER, stack_user, term->val.num);
682 break;
671 default: 683 default:
672 break; 684 break;
673 } 685 }
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index ce2d13a16226..a09b0e210997 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -65,6 +65,8 @@ enum {
65 PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ, 65 PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ,
66 PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE, 66 PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE,
67 PARSE_EVENTS__TERM_TYPE_TIME, 67 PARSE_EVENTS__TERM_TYPE_TIME,
68 PARSE_EVENTS__TERM_TYPE_CALLGRAPH,
69 PARSE_EVENTS__TERM_TYPE_STACKSIZE,
68}; 70};
69 71
70struct parse_events_term { 72struct parse_events_term {
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 4306f5ad75c7..936d566f48d8 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -185,6 +185,8 @@ period { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); }
185freq { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ); } 185freq { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ); }
186branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); } 186branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); }
187time { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_TIME); } 187time { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_TIME); }
188call-graph { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CALLGRAPH); }
189stack-size { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_STACKSIZE); }
188, { return ','; } 190, { return ','; }
189"/" { BEGIN(INITIAL); return '/'; } 191"/" { BEGIN(INITIAL); return '/'; }
190{name_minus} { return str(yyscanner, PE_NAME); } 192{name_minus} { return str(yyscanner, PE_NAME); }
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index d85f11b8cacf..84cad054d6f7 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -634,7 +634,9 @@ static char *formats_error_string(struct list_head *formats)
634{ 634{
635 struct perf_pmu_format *format; 635 struct perf_pmu_format *format;
636 char *err, *str; 636 char *err, *str;
637 static const char *static_terms = "config,config1,config2,name,period,freq,branch_type,time\n"; 637 static const char *static_terms = "config,config1,config2,name,"
638 "period,freq,branch_type,time,"
639 "call-graph,stack-size\n";
638 unsigned i = 0; 640 unsigned i = 0;
639 641
640 if (!asprintf(&str, "valid terms:")) 642 if (!asprintf(&str, "valid terms:"))