diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2010-05-23 21:36:51 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2010-05-23 21:36:51 -0400 |
commit | d67f088e084755bdceb4f15bc6e05e309db1eea7 (patch) | |
tree | 6eaae7aed4f990233e73851053f2a36b32ce55b2 /tools | |
parent | 44bf460649a9b91f291176097e9d7e846e8c001e (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')
-rw-r--r-- | tools/perf/builtin-report.c | 60 | ||||
-rw-r--r-- | tools/perf/util/hist.h | 14 | ||||
-rw-r--r-- | tools/perf/util/newt.c | 74 |
3 files changed, 108 insertions, 40 deletions
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index a7b8760e401..35920578296 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 | ||
291 | static 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 | |||
291 | static int __cmd_report(void) | 323 | static 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 | } | ||
361 | out_delete: | 373 | out_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 2d5203fedb2..83fa33a7b38 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 |
99 | static inline int hists__browse(struct hists *self __used, | 99 | static 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 | |||
106 | static inline int hists__tui_browse_tree(struct rb_root *self __used, | ||
107 | const char *help __used) | ||
108 | { | ||
109 | return 0; | ||
110 | } | ||
111 | |||
105 | static inline int hist_entry__tui_annotate(struct hist_entry *self __used) | 112 | static 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> |
113 | int hists__browse(struct hists *self, const char *helpline, | 120 | int hists__browse(struct hists *self, const char *helpline, |
114 | const char *input_name); | 121 | const char *ev_name); |
115 | int hist_entry__tui_annotate(struct hist_entry *self); | 122 | int 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 | |||
127 | int 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 ffd04720b75..d54c540f49d 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 | ||
876 | static int hist_browser__title(char *bf, size_t size, const char *input_name, | 878 | static 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 | ||
893 | int hists__browse(struct hists *self, const char *helpline, const char *input_name) | 895 | int 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; | ||
1070 | out_free_stack: | 1084 | out_free_stack: |
1071 | pstack__delete(fstack); | 1085 | pstack__delete(fstack); |
1072 | out: | 1086 | out: |
1073 | hist_browser__delete(browser); | 1087 | hist_browser__delete(browser); |
1074 | return err; | 1088 | return key; |
1089 | } | ||
1090 | |||
1091 | int 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 | ||
1077 | static struct newtPercentTreeColors { | 1123 | static struct newtPercentTreeColors { |