aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorStephane Eranian <eranian@google.com>2012-03-08 17:47:48 -0500
committerIngo Molnar <mingo@elte.hu>2012-03-09 02:26:08 -0500
commita68c2c58171391ef368fced32a555b2f0ff106e5 (patch)
tree9952e5bb45d3890e67f9f81ad704489d5a114d94 /tools/perf
parent993ac88d5892629fbe1f8a54857f9947f49f0d96 (diff)
perf report: Enable TUI in branch view mode
This patch updates perf report to support TUI mode when the perf.data file contains samples with branch stacks. For each row in the report, it is possible to annotate either the source or target of each branch. Signed-off-by: Stephane Eranian <eranian@google.com> Cc: peterz@infradead.org Cc: acme@redhat.com Cc: asharma@fb.com Cc: ravitillo@lbl.gov Cc: vweaver1@eecs.utk.edu Cc: khandual@linux.vnet.ibm.com Cc: dsahern@gmail.com Link: http://lkml.kernel.org/r/1331246868-19905-5-git-send-email-eranian@google.com Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/builtin-report.c73
-rw-r--r--tools/perf/util/session.c1
-rw-r--r--tools/perf/util/sort.h6
-rw-r--r--tools/perf/util/symbol.h7
-rw-r--r--tools/perf/util/ui/browsers/hists.c62
5 files changed, 111 insertions, 38 deletions
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 66e852376a05..8e91c6eba18a 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -64,7 +64,7 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool,
64 int err = 0; 64 int err = 0;
65 unsigned i; 65 unsigned i;
66 struct hist_entry *he; 66 struct hist_entry *he;
67 struct branch_info *bi; 67 struct branch_info *bi, *bx;
68 68
69 if ((sort__has_parent || symbol_conf.use_callchain) 69 if ((sort__has_parent || symbol_conf.use_callchain)
70 && sample->callchain) { 70 && sample->callchain) {
@@ -87,13 +87,45 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool,
87 * and not events sampled. Thus we use a pseudo period of 1. 87 * and not events sampled. Thus we use a pseudo period of 1.
88 */ 88 */
89 he = __hists__add_branch_entry(&evsel->hists, al, parent, 89 he = __hists__add_branch_entry(&evsel->hists, al, parent,
90 &bi[i], 1); 90 &bi[i], 1);
91 if (he) { 91 if (he) {
92 struct annotation *notes;
93 err = -ENOMEM;
94 bx = he->branch_info;
95 if (bx->from.sym && use_browser > 0) {
96 notes = symbol__annotation(bx->from.sym);
97 if (!notes->src
98 && symbol__alloc_hist(bx->from.sym) < 0)
99 goto out;
100
101 err = symbol__inc_addr_samples(bx->from.sym,
102 bx->from.map,
103 evsel->idx,
104 bx->from.al_addr);
105 if (err)
106 goto out;
107 }
108
109 if (bx->to.sym && use_browser > 0) {
110 notes = symbol__annotation(bx->to.sym);
111 if (!notes->src
112 && symbol__alloc_hist(bx->to.sym) < 0)
113 goto out;
114
115 err = symbol__inc_addr_samples(bx->to.sym,
116 bx->to.map,
117 evsel->idx,
118 bx->to.al_addr);
119 if (err)
120 goto out;
121 }
92 evsel->hists.stats.total_period += 1; 122 evsel->hists.stats.total_period += 1;
93 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); 123 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
124 err = 0;
94 } else 125 } else
95 return -ENOMEM; 126 return -ENOMEM;
96 } 127 }
128out:
97 return err; 129 return err;
98} 130}
99 131
@@ -615,32 +647,19 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
615 if (sort__branch_mode == -1 && has_br_stack) 647 if (sort__branch_mode == -1 && has_br_stack)
616 sort__branch_mode = 1; 648 sort__branch_mode = 1;
617 649
650 /* sort__branch_mode could be 0 if --no-branch-stack */
618 if (sort__branch_mode == 1) { 651 if (sort__branch_mode == 1) {
619 if (use_browser)
620 fprintf(stderr, "Warning: TUI interface not supported"
621 " in branch mode\n");
622 if (symbol_conf.dso_list_str != NULL)
623 fprintf(stderr, "Warning: dso filtering not supported"
624 " in branch mode\n");
625 if (symbol_conf.sym_list_str != NULL)
626 fprintf(stderr, "Warning: symbol filtering not"
627 " supported in branch mode\n");
628
629 report.use_stdio = true;
630 use_browser = 0;
631 setup_browser(true);
632 symbol_conf.dso_list_str = NULL;
633 symbol_conf.sym_list_str = NULL;
634
635 /* 652 /*
636 * if no sort_order is provided, then specify branch-mode 653 * if no sort_order is provided, then specify
637 * specific order 654 * branch-mode specific order
638 */ 655 */
639 if (sort_order == default_sort_order) 656 if (sort_order == default_sort_order)
640 sort_order = "comm,dso_from,symbol_from," 657 sort_order = "comm,dso_from,symbol_from,"
641 "dso_to,symbol_to"; 658 "dso_to,symbol_to";
642 659
643 } else if (strcmp(report.input_name, "-") != 0) { 660 }
661
662 if (strcmp(report.input_name, "-") != 0) {
644 setup_browser(true); 663 setup_browser(true);
645 } else { 664 } else {
646 use_browser = 0; 665 use_browser = 0;
@@ -696,9 +715,17 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
696 if (argc) 715 if (argc)
697 usage_with_options(report_usage, options); 716 usage_with_options(report_usage, options);
698 717
699 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "dso", stdout);
700 sort_entry__setup_elide(&sort_comm, symbol_conf.comm_list, "comm", stdout); 718 sort_entry__setup_elide(&sort_comm, symbol_conf.comm_list, "comm", stdout);
701 sort_entry__setup_elide(&sort_sym, symbol_conf.sym_list, "symbol", stdout); 719
720 if (sort__branch_mode == 1) {
721 sort_entry__setup_elide(&sort_dso_from, symbol_conf.dso_from_list, "dso_from", stdout);
722 sort_entry__setup_elide(&sort_dso_to, symbol_conf.dso_to_list, "dso_to", stdout);
723 sort_entry__setup_elide(&sort_sym_from, symbol_conf.sym_from_list, "sym_from", stdout);
724 sort_entry__setup_elide(&sort_sym_to, symbol_conf.sym_to_list, "sym_to", stdout);
725 } else {
726 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "dso", stdout);
727 sort_entry__setup_elide(&sort_sym, symbol_conf.sym_list, "symbol", stdout);
728 }
702 729
703 ret = __cmd_report(&report); 730 ret = __cmd_report(&report);
704error: 731error:
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index e650de8f4396..002ebbf59f48 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -263,6 +263,7 @@ static void ip__resolve_ams(struct machine *self, struct thread *thread,
263 } 263 }
264found: 264found:
265 ams->addr = ip; 265 ams->addr = ip;
266 ams->al_addr = al.addr;
266 ams->sym = al.sym; 267 ams->sym = al.sym;
267 ams->map = al.map; 268 ams->map = al.map;
268} 269}
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 8505b9bcfa36..472aa5a63a58 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -37,8 +37,10 @@ extern struct sort_entry sort_comm;
37extern struct sort_entry sort_dso; 37extern struct sort_entry sort_dso;
38extern struct sort_entry sort_sym; 38extern struct sort_entry sort_sym;
39extern struct sort_entry sort_parent; 39extern struct sort_entry sort_parent;
40extern struct sort_entry sort_lbr_dso; 40extern struct sort_entry sort_dso_from;
41extern struct sort_entry sort_lbr_sym; 41extern struct sort_entry sort_dso_to;
42extern struct sort_entry sort_sym_from;
43extern struct sort_entry sort_sym_to;
42extern enum sort_type sort__first_dimension; 44extern enum sort_type sort__first_dimension;
43 45
44/** 46/**
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 5866ce6b9c02..ac49ef208a5f 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -97,7 +97,11 @@ struct symbol_conf {
97 *col_width_list_str; 97 *col_width_list_str;
98 struct strlist *dso_list, 98 struct strlist *dso_list,
99 *comm_list, 99 *comm_list,
100 *sym_list; 100 *sym_list,
101 *dso_from_list,
102 *dso_to_list,
103 *sym_from_list,
104 *sym_to_list;
101 const char *symfs; 105 const char *symfs;
102}; 106};
103 107
@@ -125,6 +129,7 @@ struct addr_map_symbol {
125 struct map *map; 129 struct map *map;
126 struct symbol *sym; 130 struct symbol *sym;
127 u64 addr; 131 u64 addr;
132 u64 al_addr;
128}; 133};
129 134
130struct branch_info { 135struct branch_info {
diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c
index bfba0490c098..951e2e985c87 100644
--- a/tools/perf/util/ui/browsers/hists.c
+++ b/tools/perf/util/ui/browsers/hists.c
@@ -805,8 +805,11 @@ static struct hist_browser *hist_browser__new(struct hists *hists)
805 self->hists = hists; 805 self->hists = hists;
806 self->b.refresh = hist_browser__refresh; 806 self->b.refresh = hist_browser__refresh;
807 self->b.seek = ui_browser__hists_seek; 807 self->b.seek = ui_browser__hists_seek;
808 self->b.use_navkeypressed = true, 808 self->b.use_navkeypressed = true;
809 self->has_symbols = sort_sym.list.next != NULL; 809 if (sort__branch_mode == 1)
810 self->has_symbols = sort_sym_from.list.next != NULL;
811 else
812 self->has_symbols = sort_sym.list.next != NULL;
810 } 813 }
811 814
812 return self; 815 return self;
@@ -861,6 +864,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
861{ 864{
862 struct hists *self = &evsel->hists; 865 struct hists *self = &evsel->hists;
863 struct hist_browser *browser = hist_browser__new(self); 866 struct hist_browser *browser = hist_browser__new(self);
867 struct branch_info *bi;
864 struct pstack *fstack; 868 struct pstack *fstack;
865 int key = -1; 869 int key = -1;
866 870
@@ -879,7 +883,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
879 char *options[16]; 883 char *options[16];
880 int nr_options = 0, choice = 0, i, 884 int nr_options = 0, choice = 0, i,
881 annotate = -2, zoom_dso = -2, zoom_thread = -2, 885 annotate = -2, zoom_dso = -2, zoom_thread = -2,
882 browse_map = -2; 886 annotate_f = -2, annotate_t = -2, browse_map = -2;
883 887
884 key = hist_browser__run(browser, ev_name, timer, arg, delay_secs); 888 key = hist_browser__run(browser, ev_name, timer, arg, delay_secs);
885 889
@@ -887,7 +891,6 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
887 thread = hist_browser__selected_thread(browser); 891 thread = hist_browser__selected_thread(browser);
888 dso = browser->selection->map ? browser->selection->map->dso : NULL; 892 dso = browser->selection->map ? browser->selection->map->dso : NULL;
889 } 893 }
890
891 switch (key) { 894 switch (key) {
892 case K_TAB: 895 case K_TAB:
893 case K_UNTAB: 896 case K_UNTAB:
@@ -902,7 +905,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
902 if (!browser->has_symbols) { 905 if (!browser->has_symbols) {
903 ui_browser__warning(&browser->b, delay_secs * 2, 906 ui_browser__warning(&browser->b, delay_secs * 2,
904 "Annotation is only available for symbolic views, " 907 "Annotation is only available for symbolic views, "
905 "include \"sym\" in --sort to use it."); 908 "include \"sym*\" in --sort to use it.");
906 continue; 909 continue;
907 } 910 }
908 911
@@ -972,12 +975,32 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
972 if (!browser->has_symbols) 975 if (!browser->has_symbols)
973 goto add_exit_option; 976 goto add_exit_option;
974 977
975 if (browser->selection != NULL && 978 if (sort__branch_mode == 1) {
976 browser->selection->sym != NULL && 979 bi = browser->he_selection->branch_info;
977 !browser->selection->map->dso->annotate_warned && 980 if (browser->selection != NULL &&
978 asprintf(&options[nr_options], "Annotate %s", 981 bi &&
979 browser->selection->sym->name) > 0) 982 bi->from.sym != NULL &&
980 annotate = nr_options++; 983 !bi->from.map->dso->annotate_warned &&
984 asprintf(&options[nr_options], "Annotate %s",
985 bi->from.sym->name) > 0)
986 annotate_f = nr_options++;
987
988 if (browser->selection != NULL &&
989 bi &&
990 bi->to.sym != NULL &&
991 !bi->to.map->dso->annotate_warned &&
992 asprintf(&options[nr_options], "Annotate %s",
993 bi->to.sym->name) > 0)
994 annotate_t = nr_options++;
995 } else {
996
997 if (browser->selection != NULL &&
998 browser->selection->sym != NULL &&
999 !browser->selection->map->dso->annotate_warned &&
1000 asprintf(&options[nr_options], "Annotate %s",
1001 browser->selection->sym->name) > 0)
1002 annotate = nr_options++;
1003 }
981 1004
982 if (thread != NULL && 1005 if (thread != NULL &&
983 asprintf(&options[nr_options], "Zoom %s %s(%d) thread", 1006 asprintf(&options[nr_options], "Zoom %s %s(%d) thread",
@@ -1010,13 +1033,28 @@ add_exit_option:
1010 if (choice == -1) 1033 if (choice == -1)
1011 continue; 1034 continue;
1012 1035
1013 if (choice == annotate) { 1036 if (choice == annotate || choice == annotate_t || choice == annotate_f) {
1014 struct hist_entry *he; 1037 struct hist_entry *he;
1015 int err; 1038 int err;
1016do_annotate: 1039do_annotate:
1017 he = hist_browser__selected_entry(browser); 1040 he = hist_browser__selected_entry(browser);
1018 if (he == NULL) 1041 if (he == NULL)
1019 continue; 1042 continue;
1043
1044 /*
1045 * we stash the branch_info symbol + map into the
1046 * the ms so we don't have to rewrite all the annotation
1047 * code to use branch_info.
1048 * in branch mode, the ms struct is not used
1049 */
1050 if (choice == annotate_f) {
1051 he->ms.sym = he->branch_info->from.sym;
1052 he->ms.map = he->branch_info->from.map;
1053 } else if (choice == annotate_t) {
1054 he->ms.sym = he->branch_info->to.sym;
1055 he->ms.map = he->branch_info->to.map;
1056 }
1057
1020 /* 1058 /*
1021 * Don't let this be freed, say, by hists__decay_entry. 1059 * Don't let this be freed, say, by hists__decay_entry.
1022 */ 1060 */