aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2010-05-23 21:36:51 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2010-05-23 21:36:51 -0400
commitd67f088e084755bdceb4f15bc6e05e309db1eea7 (patch)
tree6eaae7aed4f990233e73851053f2a36b32ce55b2 /tools/perf
parent44bf460649a9b91f291176097e9d7e846e8c001e (diff)
perf report: Support multiple events on the TUI
The hists__tty_browse_tree function was created with the loop to print all events, and its equivalent, hists__tui_browse_tree, was created in a similar fashion, where it is possible to switch among the multiple events, if present, using TAB to go the next event, and shift+TAB (UNTAB) to go to the previous. The report TUI now shows as the window title the name of the event and a leak was fixed wrt pstacks. Cc: Frédéric Weisbecker <fweisbec@gmail.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Stephane Eranian <eranian@google.com> Cc: Tom Zanussi <tzanussi@gmail.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.c60
-rw-r--r--tools/perf/util/hist.h14
-rw-r--r--tools/perf/util/newt.c74
3 files changed, 108 insertions, 40 deletions
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index a7b8760e401c..359205782964 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -288,6 +288,38 @@ static size_t hists__fprintf_nr_sample_events(struct hists *self,
288 return ret + fprintf(fp, "\n#\n"); 288 return ret + fprintf(fp, "\n#\n");
289} 289}
290 290
291static int hists__tty_browse_tree(struct rb_root *tree, const char *help)
292{
293 struct rb_node *next = rb_first(tree);
294
295 while (next) {
296 struct hists *hists = rb_entry(next, struct hists, rb_node);
297 const char *evname = NULL;
298
299 if (rb_first(&hists->entries) != rb_last(&hists->entries))
300 evname = __event_name(hists->type, hists->config);
301
302 hists__fprintf_nr_sample_events(hists, evname, stdout);
303 hists__fprintf(hists, NULL, false, stdout);
304 fprintf(stdout, "\n\n");
305 next = rb_next(&hists->rb_node);
306 }
307
308 if (sort_order == default_sort_order &&
309 parent_pattern == default_parent_pattern) {
310 fprintf(stdout, "#\n# (%s)\n#\n", help);
311
312 if (show_threads) {
313 bool style = !strcmp(pretty_printing_style, "raw");
314 perf_read_values_display(stdout, &show_threads_values,
315 style);
316 perf_read_values_destroy(&show_threads_values);
317 }
318 }
319
320 return 0;
321}
322
291static int __cmd_report(void) 323static int __cmd_report(void)
292{ 324{
293 int ret = -EINVAL; 325 int ret = -EINVAL;
@@ -330,34 +362,14 @@ static int __cmd_report(void)
330 hists = rb_entry(next, struct hists, rb_node); 362 hists = rb_entry(next, struct hists, rb_node);
331 hists__collapse_resort(hists); 363 hists__collapse_resort(hists);
332 hists__output_resort(hists); 364 hists__output_resort(hists);
333 if (use_browser > 0)
334 hists__browse(hists, help, input_name);
335 else {
336 const char *evname = NULL;
337 if (rb_first(&session->hists.entries) !=
338 rb_last(&session->hists.entries))
339 evname = __event_name(hists->type, hists->config);
340
341 hists__fprintf_nr_sample_events(hists, evname, stdout);
342
343 hists__fprintf(hists, NULL, false, stdout);
344 fprintf(stdout, "\n\n");
345 }
346
347 next = rb_next(&hists->rb_node); 365 next = rb_next(&hists->rb_node);
348 } 366 }
349 367
350 if (use_browser <= 0 && sort_order == default_sort_order && 368 if (use_browser > 0)
351 parent_pattern == default_parent_pattern) { 369 hists__tui_browse_tree(&session->hists_tree, help);
352 fprintf(stdout, "#\n# (%s)\n#\n", help); 370 else
371 hists__tty_browse_tree(&session->hists_tree, help);
353 372
354 if (show_threads) {
355 bool style = !strcmp(pretty_printing_style, "raw");
356 perf_read_values_display(stdout, &show_threads_values,
357 style);
358 perf_read_values_destroy(&show_threads_values);
359 }
360 }
361out_delete: 373out_delete:
362 perf_session__delete(session); 374 perf_session__delete(session);
363 return ret; 375 return ret;
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 2d5203fedb20..83fa33a7b38b 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -98,10 +98,17 @@ void hists__filter_by_thread(struct hists *self, const struct thread *thread);
98#ifdef NO_NEWT_SUPPORT 98#ifdef NO_NEWT_SUPPORT
99static inline int hists__browse(struct hists *self __used, 99static inline int hists__browse(struct hists *self __used,
100 const char *helpline __used, 100 const char *helpline __used,
101 const char *input_name __used) 101 const char *ev_name __used)
102{ 102{
103 return 0; 103 return 0;
104} 104}
105
106static inline int hists__tui_browse_tree(struct rb_root *self __used,
107 const char *help __used)
108{
109 return 0;
110}
111
105static inline int hist_entry__tui_annotate(struct hist_entry *self __used) 112static inline int hist_entry__tui_annotate(struct hist_entry *self __used)
106{ 113{
107 return 0; 114 return 0;
@@ -111,9 +118,12 @@ static inline int hist_entry__tui_annotate(struct hist_entry *self __used)
111#else 118#else
112#include <newt.h> 119#include <newt.h>
113int hists__browse(struct hists *self, const char *helpline, 120int hists__browse(struct hists *self, const char *helpline,
114 const char *input_name); 121 const char *ev_name);
115int hist_entry__tui_annotate(struct hist_entry *self); 122int hist_entry__tui_annotate(struct hist_entry *self);
123
116#define KEY_LEFT NEWT_KEY_LEFT 124#define KEY_LEFT NEWT_KEY_LEFT
117#define KEY_RIGHT NEWT_KEY_RIGHT 125#define KEY_RIGHT NEWT_KEY_RIGHT
126
127int hists__tui_browse_tree(struct rb_root *self, const char *help);
118#endif 128#endif
119#endif /* __PERF_HIST_H */ 129#endif /* __PERF_HIST_H */
diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c
index ffd04720b754..d54c540f49db 100644
--- a/tools/perf/util/newt.c
+++ b/tools/perf/util/newt.c
@@ -842,6 +842,8 @@ static int hist_browser__populate(struct hist_browser *self, struct hists *hists
842 newtFormAddHotKey(self->form, 'h'); 842 newtFormAddHotKey(self->form, 'h');
843 newtFormAddHotKey(self->form, NEWT_KEY_F1); 843 newtFormAddHotKey(self->form, NEWT_KEY_F1);
844 newtFormAddHotKey(self->form, NEWT_KEY_RIGHT); 844 newtFormAddHotKey(self->form, NEWT_KEY_RIGHT);
845 newtFormAddHotKey(self->form, NEWT_KEY_TAB);
846 newtFormAddHotKey(self->form, NEWT_KEY_UNTAB);
845 newtFormAddComponents(self->form, self->tree, NULL); 847 newtFormAddComponents(self->form, self->tree, NULL);
846 self->selection = newt__symbol_tree_get_current(self->tree); 848 self->selection = newt__symbol_tree_get_current(self->tree);
847 849
@@ -873,7 +875,7 @@ static struct thread *hist_browser__selected_thread(struct hist_browser *self)
873 return he ? he->thread : NULL; 875 return he ? he->thread : NULL;
874} 876}
875 877
876static int hist_browser__title(char *bf, size_t size, const char *input_name, 878static int hist_browser__title(char *bf, size_t size, const char *ev_name,
877 const struct dso *dso, const struct thread *thread) 879 const struct dso *dso, const struct thread *thread)
878{ 880{
879 int printed = 0; 881 int printed = 0;
@@ -887,18 +889,18 @@ static int hist_browser__title(char *bf, size_t size, const char *input_name,
887 printed += snprintf(bf + printed, size - printed, 889 printed += snprintf(bf + printed, size - printed,
888 "%sDSO: %s", thread ? " " : "", 890 "%sDSO: %s", thread ? " " : "",
889 dso->short_name); 891 dso->short_name);
890 return printed ?: snprintf(bf, size, "Report: %s", input_name); 892 return printed ?: snprintf(bf, size, "Event: %s", ev_name);
891} 893}
892 894
893int hists__browse(struct hists *self, const char *helpline, const char *input_name) 895int hists__browse(struct hists *self, const char *helpline, const char *ev_name)
894{ 896{
895 struct hist_browser *browser = hist_browser__new(); 897 struct hist_browser *browser = hist_browser__new();
896 struct pstack *fstack = pstack__new(2); 898 struct pstack *fstack;
897 const struct thread *thread_filter = NULL; 899 const struct thread *thread_filter = NULL;
898 const struct dso *dso_filter = NULL; 900 const struct dso *dso_filter = NULL;
899 struct newtExitStruct es; 901 struct newtExitStruct es;
900 char msg[160]; 902 char msg[160];
901 int err = -1; 903 int key = -1;
902 904
903 if (browser == NULL) 905 if (browser == NULL)
904 return -1; 906 return -1;
@@ -909,7 +911,7 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na
909 911
910 ui_helpline__push(helpline); 912 ui_helpline__push(helpline);
911 913
912 hist_browser__title(msg, sizeof(msg), input_name, 914 hist_browser__title(msg, sizeof(msg), ev_name,
913 dso_filter, thread_filter); 915 dso_filter, thread_filter);
914 if (hist_browser__populate(browser, self, msg) < 0) 916 if (hist_browser__populate(browser, self, msg) < 0)
915 goto out_free_stack; 917 goto out_free_stack;
@@ -927,10 +929,23 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na
927 dso = browser->selection->map ? browser->selection->map->dso : NULL; 929 dso = browser->selection->map ? browser->selection->map->dso : NULL;
928 930
929 if (es.reason == NEWT_EXIT_HOTKEY) { 931 if (es.reason == NEWT_EXIT_HOTKEY) {
930 if (es.u.key == NEWT_KEY_F1) 932 key = es.u.key;
933
934 switch (key) {
935 case NEWT_KEY_F1:
931 goto do_help; 936 goto do_help;
937 case NEWT_KEY_TAB:
938 case NEWT_KEY_UNTAB:
939 /*
940 * Exit the browser, let hists__browser_tree
941 * go to the next or previous
942 */
943 goto out_free_stack;
944 default:;
945 }
932 946
933 switch (toupper(es.u.key)) { 947 key = toupper(key);
948 switch (key) {
934 case 'A': 949 case 'A':
935 if (browser->selection->map == NULL && 950 if (browser->selection->map == NULL &&
936 browser->selection->map->dso->annotate_warned) 951 browser->selection->map->dso->annotate_warned)
@@ -953,8 +968,8 @@ do_help:
953 continue; 968 continue;
954 default:; 969 default:;
955 } 970 }
956 if (is_exit_key(es.u.key)) { 971 if (is_exit_key(key)) {
957 if (es.u.key == NEWT_KEY_ESCAPE) { 972 if (key == NEWT_KEY_ESCAPE) {
958 if (dialog_yesno("Do you really want to exit?")) 973 if (dialog_yesno("Do you really want to exit?"))
959 break; 974 break;
960 else 975 else
@@ -1041,7 +1056,7 @@ zoom_out_dso:
1041 pstack__push(fstack, &dso_filter); 1056 pstack__push(fstack, &dso_filter);
1042 } 1057 }
1043 hists__filter_by_dso(self, dso_filter); 1058 hists__filter_by_dso(self, dso_filter);
1044 hist_browser__title(msg, sizeof(msg), input_name, 1059 hist_browser__title(msg, sizeof(msg), ev_name,
1045 dso_filter, thread_filter); 1060 dso_filter, thread_filter);
1046 if (hist_browser__populate(browser, self, msg) < 0) 1061 if (hist_browser__populate(browser, self, msg) < 0)
1047 goto out; 1062 goto out;
@@ -1060,18 +1075,49 @@ zoom_out_thread:
1060 pstack__push(fstack, &thread_filter); 1075 pstack__push(fstack, &thread_filter);
1061 } 1076 }
1062 hists__filter_by_thread(self, thread_filter); 1077 hists__filter_by_thread(self, thread_filter);
1063 hist_browser__title(msg, sizeof(msg), input_name, 1078 hist_browser__title(msg, sizeof(msg), ev_name,
1064 dso_filter, thread_filter); 1079 dso_filter, thread_filter);
1065 if (hist_browser__populate(browser, self, msg) < 0) 1080 if (hist_browser__populate(browser, self, msg) < 0)
1066 goto out; 1081 goto out;
1067 } 1082 }
1068 } 1083 }
1069 err = 0;
1070out_free_stack: 1084out_free_stack:
1071 pstack__delete(fstack); 1085 pstack__delete(fstack);
1072out: 1086out:
1073 hist_browser__delete(browser); 1087 hist_browser__delete(browser);
1074 return err; 1088 return key;
1089}
1090
1091int hists__tui_browse_tree(struct rb_root *self, const char *help)
1092{
1093 struct rb_node *first = rb_first(self), *nd = first, *next;
1094 int key = 0;
1095
1096 while (nd) {
1097 struct hists *hists = rb_entry(nd, struct hists, rb_node);
1098 const char *ev_name = __event_name(hists->type, hists->config);
1099
1100 key = hists__browse(hists, help, ev_name);
1101
1102 if (is_exit_key(key))
1103 break;
1104
1105 switch (key) {
1106 case NEWT_KEY_TAB:
1107 next = rb_next(nd);
1108 if (next)
1109 nd = next;
1110 break;
1111 case NEWT_KEY_UNTAB:
1112 if (nd == first)
1113 continue;
1114 nd = rb_prev(nd);
1115 default:
1116 break;
1117 }
1118 }
1119
1120 return key;
1075} 1121}
1076 1122
1077static struct newtPercentTreeColors { 1123static struct newtPercentTreeColors {