aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2011-03-06 11:07:30 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2011-03-06 11:14:53 -0500
commit7f0030b211579939461468f25b80c73e293c46e0 (patch)
treee0992d0a0c958526df603f9c18671a9612ff5b75 /tools/perf
parente248de331a452f8771eda6ed4bb30d92c82df28b (diff)
perf report tui: Improve multi event session support
When multiple events were used in 'perf record', allow the user to choose which one is wanted before showing the per event histograms. Annotations will be performed on the chosen event. Allow going back and forth from event to event quickly using just the arrow keys and enter. Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Cc: Tom Zanussi <tzanussi@gmail.com> Cc: William Cohen <wcohen@redhat.com> LKML-Reference: <new-submission> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/builtin-report.c7
-rw-r--r--tools/perf/util/hist.h16
-rw-r--r--tools/perf/util/ui/browsers/hists.c147
3 files changed, 140 insertions, 30 deletions
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 1c399eae5f7b..e9b5d513333a 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -222,7 +222,8 @@ static size_t hists__fprintf_nr_sample_events(struct hists *self,
222 return ret + fprintf(fp, "\n#\n"); 222 return ret + fprintf(fp, "\n#\n");
223} 223}
224 224
225static int hists__tty_browse_tree(struct perf_evlist *evlist, const char *help) 225static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
226 const char *help)
226{ 227{
227 struct perf_evsel *pos; 228 struct perf_evsel *pos;
228 229
@@ -304,9 +305,9 @@ static int __cmd_report(void)
304 } 305 }
305 306
306 if (use_browser > 0) 307 if (use_browser > 0)
307 hists__tui_browse_tree(session->evlist, help); 308 perf_evlist__tui_browse_hists(session->evlist, help);
308 else 309 else
309 hists__tty_browse_tree(session->evlist, help); 310 perf_evlist__tty_browse_hists(session->evlist, help);
310 311
311out_delete: 312out_delete:
312 /* 313 /*
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 0d38b435827b..cb6858a2f9a3 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -87,15 +87,9 @@ bool hists__new_col_len(struct hists *self, enum hist_column col, u16 len);
87struct perf_evlist; 87struct perf_evlist;
88 88
89#ifdef NO_NEWT_SUPPORT 89#ifdef NO_NEWT_SUPPORT
90static inline int hists__browse(struct hists *self __used, 90static inline
91 const char *helpline __used, 91int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __used,
92 const char *ev_name __used, int evidx __used) 92 const char *help __used)
93{
94 return 0;
95}
96
97static inline int hists__tui_browse_tree(struct perf_evlist *evlist __used,
98 const char *help __used)
99{ 93{
100 return 0; 94 return 0;
101} 95}
@@ -109,14 +103,12 @@ static inline int hist_entry__tui_annotate(struct hist_entry *self __used,
109#define KEY_RIGHT -2 103#define KEY_RIGHT -2
110#else 104#else
111#include <newt.h> 105#include <newt.h>
112int hists__browse(struct hists *self, const char *helpline,
113 const char *ev_name, int evidx);
114int hist_entry__tui_annotate(struct hist_entry *self, int evidx); 106int hist_entry__tui_annotate(struct hist_entry *self, int evidx);
115 107
116#define KEY_LEFT NEWT_KEY_LEFT 108#define KEY_LEFT NEWT_KEY_LEFT
117#define KEY_RIGHT NEWT_KEY_RIGHT 109#define KEY_RIGHT NEWT_KEY_RIGHT
118 110
119int hists__tui_browse_tree(struct perf_evlist *evlist, const char *help); 111int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help);
120#endif 112#endif
121 113
122unsigned int hists__sort_list_width(struct hists *self); 114unsigned int hists__sort_list_width(struct hists *self);
diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c
index f3af4fe5cdc4..798efdca3ead 100644
--- a/tools/perf/util/ui/browsers/hists.c
+++ b/tools/perf/util/ui/browsers/hists.c
@@ -803,9 +803,11 @@ static int hists__browser_title(struct hists *self, char *bf, size_t size,
803 return printed; 803 return printed;
804} 804}
805 805
806int hists__browse(struct hists *self, const char *helpline, 806static int perf_evsel__hists_browse(struct perf_evsel *evsel,
807 const char *ev_name, int evidx) 807 const char *helpline, const char *ev_name,
808 bool left_exits)
808{ 809{
810 struct hists *self = &evsel->hists;
809 struct hist_browser *browser = hist_browser__new(self); 811 struct hist_browser *browser = hist_browser__new(self);
810 struct pstack *fstack; 812 struct pstack *fstack;
811 const struct thread *thread_filter = NULL; 813 const struct thread *thread_filter = NULL;
@@ -878,8 +880,14 @@ int hists__browse(struct hists *self, const char *helpline,
878 case NEWT_KEY_LEFT: { 880 case NEWT_KEY_LEFT: {
879 const void *top; 881 const void *top;
880 882
881 if (pstack__empty(fstack)) 883 if (pstack__empty(fstack)) {
884 /*
885 * Go back to the perf_evsel_menu__run or other user
886 */
887 if (left_exits)
888 goto out_free_stack;
882 continue; 889 continue;
890 }
883 top = pstack__pop(fstack); 891 top = pstack__pop(fstack);
884 if (top == &dso_filter) 892 if (top == &dso_filter)
885 goto zoom_out_dso; 893 goto zoom_out_dso;
@@ -888,7 +896,8 @@ int hists__browse(struct hists *self, const char *helpline,
888 continue; 896 continue;
889 } 897 }
890 case NEWT_KEY_ESCAPE: 898 case NEWT_KEY_ESCAPE:
891 if (!ui__dialog_yesno("Do you really want to exit?")) 899 if (!left_exits &&
900 !ui__dialog_yesno("Do you really want to exit?"))
892 continue; 901 continue;
893 /* Fall thru */ 902 /* Fall thru */
894 default: 903 default:
@@ -940,7 +949,7 @@ do_annotate:
940 if (he == NULL) 949 if (he == NULL)
941 continue; 950 continue;
942 951
943 hist_entry__tui_annotate(he, evidx); 952 hist_entry__tui_annotate(he, evsel->idx);
944 } else if (choice == browse_map) 953 } else if (choice == browse_map)
945 map__browse(browser->selection->map); 954 map__browse(browser->selection->map);
946 else if (choice == zoom_dso) { 955 else if (choice == zoom_dso) {
@@ -989,15 +998,71 @@ out:
989 return key; 998 return key;
990} 999}
991 1000
992int hists__tui_browse_tree(struct perf_evlist *evlist, const char *help) 1001struct perf_evsel_menu {
1002 struct ui_browser b;
1003 struct perf_evsel *selection;
1004};
1005
1006static void perf_evsel_menu__write(struct ui_browser *browser,
1007 void *entry, int row)
1008{
1009 struct perf_evsel_menu *menu = container_of(browser,
1010 struct perf_evsel_menu, b);
1011 struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node);
1012 bool current_entry = ui_browser__is_current_entry(browser, row);
1013 unsigned long nr_events = evsel->hists.stats.nr_events[PERF_RECORD_SAMPLE];
1014 const char *ev_name = event_name(evsel);
1015 char bf[256], unit;
1016
1017 ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
1018 HE_COLORSET_NORMAL);
1019
1020 nr_events = convert_unit(nr_events, &unit);
1021 snprintf(bf, sizeof(bf), "%lu%c%s%s", nr_events,
1022 unit, unit == ' ' ? "" : " ", ev_name);
1023 slsmg_write_nstring(bf, browser->width);
1024
1025 if (current_entry)
1026 menu->selection = evsel;
1027}
1028
1029static int perf_evsel_menu__run(struct perf_evsel_menu *menu, const char *help)
993{ 1030{
1031 int exit_keys[] = { NEWT_KEY_ENTER, NEWT_KEY_RIGHT, 0, };
1032 struct perf_evlist *evlist = menu->b.priv;
994 struct perf_evsel *pos; 1033 struct perf_evsel *pos;
1034 const char *ev_name, *title = "Available samples";
1035 int key;
995 1036
996 pos = list_entry(evlist->entries.next, struct perf_evsel, node); 1037 if (ui_browser__show(&menu->b, title,
997 while (pos) { 1038 "ESC: exit, ENTER|->: Browse histograms") < 0)
998 struct hists *hists = &pos->hists; 1039 return -1;
999 const char *ev_name = event_name(pos); 1040
1000 int key = hists__browse(hists, help, ev_name, pos->idx); 1041 ui_browser__add_exit_keys(&menu->b, exit_keys);
1042
1043 while (1) {
1044 key = ui_browser__run(&menu->b);
1045
1046 switch (key) {
1047 case NEWT_KEY_RIGHT:
1048 case NEWT_KEY_ENTER:
1049 if (!menu->selection)
1050 continue;
1051 pos = menu->selection;
1052browse_hists:
1053 ev_name = event_name(pos);
1054 key = perf_evsel__hists_browse(pos, help, ev_name, true);
1055 ui_browser__show_title(&menu->b, title);
1056 break;
1057 case NEWT_KEY_LEFT:
1058 continue;
1059 case NEWT_KEY_ESCAPE:
1060 if (!ui__dialog_yesno("Do you really want to exit?"))
1061 continue;
1062 /* Fall thru */
1063 default:
1064 goto out;
1065 }
1001 1066
1002 switch (key) { 1067 switch (key) {
1003 case NEWT_KEY_TAB: 1068 case NEWT_KEY_TAB:
@@ -1005,17 +1070,69 @@ int hists__tui_browse_tree(struct perf_evlist *evlist, const char *help)
1005 pos = list_entry(evlist->entries.next, struct perf_evsel, node); 1070 pos = list_entry(evlist->entries.next, struct perf_evsel, node);
1006 else 1071 else
1007 pos = list_entry(pos->node.next, struct perf_evsel, node); 1072 pos = list_entry(pos->node.next, struct perf_evsel, node);
1008 break; 1073 goto browse_hists;
1009 case NEWT_KEY_UNTAB: 1074 case NEWT_KEY_UNTAB:
1010 if (pos->node.prev == &evlist->entries) 1075 if (pos->node.prev == &evlist->entries)
1011 pos = list_entry(evlist->entries.prev, struct perf_evsel, node); 1076 pos = list_entry(evlist->entries.prev, struct perf_evsel, node);
1012 else 1077 else
1013 pos = list_entry(pos->node.prev, struct perf_evsel, node); 1078 pos = list_entry(pos->node.prev, struct perf_evsel, node);
1014 break; 1079 goto browse_hists;
1080 case 'q':
1081 case CTRL('c'):
1082 goto out;
1015 default: 1083 default:
1016 return key; 1084 break;
1017 } 1085 }
1018 } 1086 }
1019 1087
1020 return 0; 1088out:
1089 ui_browser__hide(&menu->b);
1090 return key;
1091}
1092
1093static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
1094 const char *help)
1095{
1096 struct perf_evsel *pos;
1097 struct perf_evsel_menu menu = {
1098 .b = {
1099 .entries = &evlist->entries,
1100 .refresh = ui_browser__list_head_refresh,
1101 .seek = ui_browser__list_head_seek,
1102 .write = perf_evsel_menu__write,
1103 .nr_entries = evlist->nr_entries,
1104 .priv = evlist,
1105 },
1106 };
1107
1108 ui_helpline__push("Press ESC to exit");
1109
1110 list_for_each_entry(pos, &evlist->entries, node) {
1111 const char *ev_name = event_name(pos);
1112 size_t line_len = strlen(ev_name) + 7;
1113
1114 if (menu.b.width < line_len)
1115 menu.b.width = line_len;
1116 /*
1117 * Cache the evsel name, tracepoints have a _high_ cost per
1118 * event_name() call.
1119 */
1120 if (pos->name == NULL)
1121 pos->name = strdup(ev_name);
1122 }
1123
1124 return perf_evsel_menu__run(&menu, help);
1125}
1126
1127int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help)
1128{
1129
1130 if (evlist->nr_entries == 1) {
1131 struct perf_evsel *first = list_entry(evlist->entries.next,
1132 struct perf_evsel, node);
1133 const char *ev_name = event_name(first);
1134 return perf_evsel__hists_browse(first, help, ev_name, false);
1135 }
1136
1137 return __perf_evlist__tui_browse_hists(evlist, help);
1021} 1138}