aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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}