aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2011-01-31 15:19:33 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2011-01-31 15:19:33 -0500
commitc0443df1b69b59675fc6790e0ddce87c8ca00abf (patch)
tree8c98a270700f594d0e49246a640a4f725caf9bf1
parent229ade9ba36341f7369ecb4f134bcec9133520bf (diff)
perf top: Introduce slang based TUI
Disabled by default as there are features found in the stdio based one that aren't implemented, like live annotation, filtering knobs data entry. Annotation hopefully will get somehow merged with the 'perf annotate' code. To use it: perf top --tui 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> LKML-Reference: <new-submission> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/Makefile4
-rw-r--r--tools/perf/builtin-top.c35
-rw-r--r--tools/perf/util/top.c7
-rw-r--r--tools/perf/util/top.h15
-rw-r--r--tools/perf/util/ui/browsers/top.c136
5 files changed, 189 insertions, 8 deletions
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index edc660e0bc2f..67a9f4d805de 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -621,6 +621,7 @@ else
621 LIB_OBJS += $(OUTPUT)util/ui/browsers/annotate.o 621 LIB_OBJS += $(OUTPUT)util/ui/browsers/annotate.o
622 LIB_OBJS += $(OUTPUT)util/ui/browsers/hists.o 622 LIB_OBJS += $(OUTPUT)util/ui/browsers/hists.o
623 LIB_OBJS += $(OUTPUT)util/ui/browsers/map.o 623 LIB_OBJS += $(OUTPUT)util/ui/browsers/map.o
624 LIB_OBJS += $(OUTPUT)util/ui/browsers/top.o
624 LIB_OBJS += $(OUTPUT)util/ui/helpline.o 625 LIB_OBJS += $(OUTPUT)util/ui/helpline.o
625 LIB_OBJS += $(OUTPUT)util/ui/progress.o 626 LIB_OBJS += $(OUTPUT)util/ui/progress.o
626 LIB_OBJS += $(OUTPUT)util/ui/util.o 627 LIB_OBJS += $(OUTPUT)util/ui/util.o
@@ -1050,6 +1051,9 @@ $(OUTPUT)util/ui/browser.o: util/ui/browser.c $(OUTPUT)PERF-CFLAGS
1050$(OUTPUT)util/ui/browsers/annotate.o: util/ui/browsers/annotate.c $(OUTPUT)PERF-CFLAGS 1051$(OUTPUT)util/ui/browsers/annotate.o: util/ui/browsers/annotate.c $(OUTPUT)PERF-CFLAGS
1051 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $< 1052 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
1052 1053
1054$(OUTPUT)util/ui/browsers/top.o: util/ui/browsers/top.c $(OUTPUT)PERF-CFLAGS
1055 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
1056
1053$(OUTPUT)util/ui/browsers/hists.o: util/ui/browsers/hists.c $(OUTPUT)PERF-CFLAGS 1057$(OUTPUT)util/ui/browsers/hists.o: util/ui/browsers/hists.c $(OUTPUT)PERF-CFLAGS
1054 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $< 1058 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
1055 1059
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 3c9ba943aa48..104de9ab314c 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -20,6 +20,7 @@
20 20
21#include "perf.h" 21#include "perf.h"
22 22
23#include "util/cache.h"
23#include "util/color.h" 24#include "util/color.h"
24#include "util/evlist.h" 25#include "util/evlist.h"
25#include "util/evsel.h" 26#include "util/evsel.h"
@@ -75,6 +76,8 @@ static struct perf_top top = {
75 76
76static bool system_wide = false; 77static bool system_wide = false;
77 78
79static bool use_tui, use_stdio;
80
78static int default_interval = 0; 81static int default_interval = 0;
79 82
80static bool inherit = false; 83static bool inherit = false;
@@ -96,11 +99,6 @@ static int sym_pcnt_filter = 5;
96 * Source functions 99 * Source functions
97 */ 100 */
98 101
99static inline struct symbol *sym_entry__symbol(struct sym_entry *self)
100{
101 return ((void *)self) + symbol_conf.priv_size;
102}
103
104void get_term_dimensions(struct winsize *ws) 102void get_term_dimensions(struct winsize *ws)
105{ 103{
106 char *s = getenv("LINES"); 104 char *s = getenv("LINES");
@@ -695,6 +693,14 @@ static void handle_keypress(struct perf_session *session, int c)
695 } 693 }
696} 694}
697 695
696static void *display_thread_tui(void *arg __used)
697{
698 perf_top__tui_browser(&top);
699 exit_browser(0);
700 exit(0);
701 return NULL;
702}
703
698static void *display_thread(void *arg __used) 704static void *display_thread(void *arg __used)
699{ 705{
700 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; 706 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
@@ -1005,7 +1011,8 @@ static int __cmd_top(void)
1005 1011
1006 perf_session__mmap_read(session); 1012 perf_session__mmap_read(session);
1007 1013
1008 if (pthread_create(&thread, NULL, display_thread, session)) { 1014 if (pthread_create(&thread, NULL, (use_browser > 0 ? display_thread_tui :
1015 display_thread), session)) {
1009 printf("Could not create display thread.\n"); 1016 printf("Could not create display thread.\n");
1010 exit(-1); 1017 exit(-1);
1011 } 1018 }
@@ -1078,6 +1085,8 @@ static const struct option options[] = {
1078 "display this many functions"), 1085 "display this many functions"),
1079 OPT_BOOLEAN('U', "hide_user_symbols", &top.hide_user_symbols, 1086 OPT_BOOLEAN('U', "hide_user_symbols", &top.hide_user_symbols,
1080 "hide user symbols"), 1087 "hide user symbols"),
1088 OPT_BOOLEAN(0, "tui", &use_tui, "Use the TUI interface"),
1089 OPT_BOOLEAN(0, "stdio", &use_stdio, "Use the stdio interface"),
1081 OPT_INCR('v', "verbose", &verbose, 1090 OPT_INCR('v', "verbose", &verbose,
1082 "be more verbose (show counter open errors, etc)"), 1091 "be more verbose (show counter open errors, etc)"),
1083 OPT_END() 1092 OPT_END()
@@ -1098,6 +1107,20 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1098 if (argc) 1107 if (argc)
1099 usage_with_options(top_usage, options); 1108 usage_with_options(top_usage, options);
1100 1109
1110 /*
1111 * XXX For now start disabled, only using TUI if explicitely asked for.
1112 * Change that when handle_keys equivalent gets written, live annotation
1113 * done, etc.
1114 */
1115 use_browser = 0;
1116
1117 if (use_stdio)
1118 use_browser = 0;
1119 else if (use_tui)
1120 use_browser = 1;
1121
1122 setup_browser(false);
1123
1101 /* CPU and PID are mutually exclusive */ 1124 /* CPU and PID are mutually exclusive */
1102 if (top.target_tid > 0 && top.cpu_list) { 1125 if (top.target_tid > 0 && top.cpu_list) {
1103 printf("WARNING: PID switch overriding CPU\n"); 1126 printf("WARNING: PID switch overriding CPU\n");
diff --git a/tools/perf/util/top.c b/tools/perf/util/top.c
index c06cc5386e7e..1d2e2652cd68 100644
--- a/tools/perf/util/top.c
+++ b/tools/perf/util/top.c
@@ -158,6 +158,7 @@ float perf_top__decay_samples(struct perf_top *top, struct rb_root *root)
158 syme = list_entry(top->active_symbols.next, struct sym_entry, node); 158 syme = list_entry(top->active_symbols.next, struct sym_entry, node);
159 pthread_mutex_unlock(&top->active_symbols_lock); 159 pthread_mutex_unlock(&top->active_symbols_lock);
160 160
161 top->rb_entries = 0;
161 list_for_each_entry_safe_from(syme, n, &top->active_symbols, node) { 162 list_for_each_entry_safe_from(syme, n, &top->active_symbols, node) {
162 syme->snap_count = syme->count[snap]; 163 syme->snap_count = syme->count[snap];
163 if (syme->snap_count != 0) { 164 if (syme->snap_count != 0) {
@@ -170,7 +171,11 @@ float perf_top__decay_samples(struct perf_top *top, struct rb_root *root)
170 continue; 171 continue;
171 } 172 }
172 syme->weight = sym_weight(syme, top); 173 syme->weight = sym_weight(syme, top);
173 rb_insert_active_sym(root, syme); 174
175 if ((int)syme->snap_count >= top->count_filter) {
176 rb_insert_active_sym(root, syme);
177 ++top->rb_entries;
178 }
174 sum_ksamples += syme->snap_count; 179 sum_ksamples += syme->snap_count;
175 180
176 for (j = 0; j < top->evlist->nr_entries; j++) 181 for (j = 0; j < top->evlist->nr_entries; j++)
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index 0467b26dd8d8..611370fa7df8 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -38,6 +38,11 @@ struct sym_entry {
38 unsigned long count[0]; 38 unsigned long count[0];
39}; 39};
40 40
41static inline struct symbol *sym_entry__symbol(struct sym_entry *self)
42{
43 return ((void *)self) + symbol_conf.priv_size;
44}
45
41struct perf_top { 46struct perf_top {
42 struct perf_evlist *evlist; 47 struct perf_evlist *evlist;
43 /* 48 /*
@@ -51,7 +56,7 @@ struct perf_top {
51 u64 exact_samples; 56 u64 exact_samples;
52 u64 guest_us_samples, guest_kernel_samples; 57 u64 guest_us_samples, guest_kernel_samples;
53 int print_entries, count_filter, delay_secs; 58 int print_entries, count_filter, delay_secs;
54 int display_weighted, freq; 59 int display_weighted, freq, rb_entries;
55 int sym_counter, target_pid, target_tid; 60 int sym_counter, target_pid, target_tid;
56 bool hide_kernel_symbols, hide_user_symbols, zero; 61 bool hide_kernel_symbols, hide_user_symbols, zero;
57 const char *cpu_list; 62 const char *cpu_list;
@@ -64,4 +69,12 @@ float perf_top__decay_samples(struct perf_top *top, struct rb_root *root);
64void perf_top__find_widths(struct perf_top *top, struct rb_root *root, 69void perf_top__find_widths(struct perf_top *top, struct rb_root *root,
65 int *dso_width, int *dso_short_width, int *sym_width); 70 int *dso_width, int *dso_short_width, int *sym_width);
66 71
72#ifdef NO_NEWT_SUPPORT
73static inline int perf_top__tui_browser(struct perf_top *top __used)
74{
75 return 0;
76}
77#else
78int perf_top__tui_browser(struct perf_top *top);
79#endif
67#endif /* __PERF_TOP_H */ 80#endif /* __PERF_TOP_H */
diff --git a/tools/perf/util/ui/browsers/top.c b/tools/perf/util/ui/browsers/top.c
new file mode 100644
index 000000000000..ca6062483a8f
--- /dev/null
+++ b/tools/perf/util/ui/browsers/top.c
@@ -0,0 +1,136 @@
1/*
2 * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
3 *
4 * Parts came from builtin-{top,stat,record}.c, see those files for further
5 * copyright notes.
6 *
7 * Released under the GPL v2. (and only v2, not any later version)
8 */
9#include "../browser.h"
10#include "../helpline.h"
11#include "../libslang.h"
12#include "../../evlist.h"
13#include "../../hist.h"
14#include "../../sort.h"
15#include "../../symbol.h"
16#include "../../top.h"
17
18struct perf_top_browser {
19 struct ui_browser b;
20 struct rb_root root;
21 float sum_ksamples;
22 int dso_width;
23 int dso_short_width;
24 int sym_width;
25};
26
27static void perf_top_browser__write(struct ui_browser *browser, void *entry, int row)
28{
29 struct perf_top_browser *top_browser = container_of(browser, struct perf_top_browser, b);
30 struct sym_entry *syme = rb_entry(entry, struct sym_entry, rb_node);
31 bool current_entry = ui_browser__is_current_entry(browser, row);
32 struct symbol *symbol = sym_entry__symbol(syme);
33 struct perf_top *top = browser->priv;
34 int width = browser->width;
35 double pcnt;
36
37 pcnt = 100.0 - (100.0 * ((top_browser->sum_ksamples - syme->snap_count) /
38 top_browser->sum_ksamples));
39 ui_browser__set_percent_color(browser, pcnt, current_entry);
40
41 if (top->evlist->nr_entries == 1 || !top->display_weighted) {
42 slsmg_printf("%20.2f ", syme->weight);
43 width -= 24;
44 } else {
45 slsmg_printf("%9.1f %10ld ", syme->weight, syme->snap_count);
46 width -= 23;
47 }
48
49 slsmg_printf("%4.1f%%", pcnt);
50 width -= 7;
51
52 if (verbose) {
53 slsmg_printf(" %016" PRIx64, symbol->start);
54 width -= 17;
55 }
56
57 slsmg_printf(" %-*.*s ", top_browser->sym_width, top_browser->sym_width,
58 symbol->name);
59 width -= top_browser->sym_width;
60 slsmg_write_nstring(width >= syme->map->dso->long_name_len ?
61 syme->map->dso->long_name :
62 syme->map->dso->short_name, width);
63}
64
65static void perf_top_browser__update_rb_tree(struct perf_top_browser *browser)
66{
67 struct perf_top *top = browser->b.priv;
68
69 browser->root = RB_ROOT;
70 browser->b.top = NULL;
71 browser->sum_ksamples = perf_top__decay_samples(top, &browser->root);
72 perf_top__find_widths(top, &browser->root, &browser->dso_width,
73 &browser->dso_short_width,
74 &browser->sym_width);
75 if (browser->sym_width + browser->dso_width > browser->b.width - 29) {
76 browser->dso_width = browser->dso_short_width;
77 if (browser->sym_width + browser->dso_width > browser->b.width - 29)
78 browser->sym_width = browser->b.width - browser->dso_width - 29;
79 }
80 browser->b.nr_entries = top->rb_entries;
81}
82
83static int perf_top_browser__run(struct perf_top_browser *browser)
84{
85 int key;
86 char title[160];
87 struct perf_top *top = browser->b.priv;
88 int delay_msecs = top->delay_secs * 1000;
89
90 perf_top_browser__update_rb_tree(browser);
91 perf_top__header_snprintf(top, title, sizeof(title));
92 perf_top__reset_sample_counters(top);
93
94 if (ui_browser__show(&browser->b, title, "ESC: exit") < 0)
95 return -1;
96
97 newtFormSetTimer(browser->b.form, delay_msecs);
98
99 while (1) {
100 key = ui_browser__run(&browser->b);
101
102 switch (key) {
103 case -1:
104 /* FIXME we need to check if it was es.reason == NEWT_EXIT_TIMER */
105 perf_top_browser__update_rb_tree(browser);
106 perf_top__header_snprintf(top, title, sizeof(title));
107 perf_top__reset_sample_counters(top);
108 ui_browser__set_color(&browser->b, NEWT_COLORSET_ROOT);
109 SLsmg_gotorc(0, 0);
110 slsmg_write_nstring(title, browser->b.width);
111 break;
112 case NEWT_KEY_TAB:
113 default:
114 goto out;
115 }
116 }
117out:
118 ui_browser__hide(&browser->b);
119 return key;
120}
121
122int perf_top__tui_browser(struct perf_top *top)
123{
124 struct perf_top_browser browser = {
125 .b = {
126 .entries = &browser.root,
127 .refresh = ui_browser__rb_tree_refresh,
128 .seek = ui_browser__rb_tree_seek,
129 .write = perf_top_browser__write,
130 .priv = top,
131 },
132 };
133
134 ui_helpline__push("Press <- or ESC to exit");
135 return perf_top_browser__run(&browser);
136}