aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorPekka Enberg <penberg@kernel.org>2012-03-19 14:13:29 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2012-03-19 14:13:29 -0400
commitc31a94570552dcaa517c4f7a043ffd28835016be (patch)
treedb6b03aaca5ca4a254912ae1a7f3e5e89ee182e4 /tools
parentfde0eeaba7fe18dfd2ee6142fb562123e510ef84 (diff)
perf report: Add a simple GTK2-based 'perf report' browser
This patch adds a simple GTK2-based browser to 'perf report' that's based on the TTY-based browser in builtin-report.c. To launch "perf report" using the new GTK interface just type: $ perf report --gtk The interface is somewhat limited in features at the moment: - No callgraph support - No KVM guest profiling support - No color coding for percentages - No sorting from the UI - ..and many, many more! That said, I think this patch a reasonable start to build future features on. Signed-off-by: Pekka Enberg <penberg@kernel.org> Cc: Colin Walters <walters@verbum.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Paul Mackerras <paulus@samba.org> Cc: Ingo Molnar <mingo@kernel.org> Link: http://lkml.kernel.org/r/alpine.LFD.2.02.1202231952410.6689@tux.localdomain [ committer note: Added #pragma to make gtk no strict prototype problem go away as suggested by Colin Walters modulo avoiding push/pop ] Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/Documentation/perf-report.txt2
-rw-r--r--tools/perf/Makefile14
-rw-r--r--tools/perf/builtin-report.c19
-rw-r--r--tools/perf/config/feature-tests.mak15
-rw-r--r--tools/perf/util/cache.h12
-rw-r--r--tools/perf/util/gtk/browser.c189
-rw-r--r--tools/perf/util/gtk/gtk.h8
-rw-r--r--tools/perf/util/hist.h17
8 files changed, 272 insertions, 4 deletions
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 68bbf9cec4b7..2d89f02719b5 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -113,6 +113,8 @@ OPTIONS
113 requires a tty, if one is not present, as when piping to other 113 requires a tty, if one is not present, as when piping to other
114 commands, the stdio interface is used. 114 commands, the stdio interface is used.
115 115
116--gtk:: Use the GTK2 interface.
117
116-k:: 118-k::
117--vmlinux=<file>:: 119--vmlinux=<file>::
118 vmlinux pathname 120 vmlinux pathname
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index e07fbd838749..cc27148635cd 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -507,6 +507,20 @@ else
507 endif 507 endif
508endif 508endif
509 509
510ifdef NO_GTK2
511 BASIC_CFLAGS += -DNO_GTK2
512else
513 FLAGS_GTK2=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) $(shell pkg-config --libs --cflags gtk+-2.0)
514 ifneq ($(call try-cc,$(SOURCE_GTK2),$(FLAGS_GTK2)),y)
515 msg := $(warning GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev);
516 BASIC_CFLAGS += -DNO_GTK2_SUPPORT
517 else
518 BASIC_CFLAGS += $(shell pkg-config --cflags gtk+-2.0)
519 EXTLIBS += $(shell pkg-config --libs gtk+-2.0)
520 LIB_OBJS += $(OUTPUT)util/gtk/browser.o
521 endif
522endif
523
510ifdef NO_LIBPERL 524ifdef NO_LIBPERL
511 BASIC_CFLAGS += -DNO_LIBPERL 525 BASIC_CFLAGS += -DNO_LIBPERL
512else 526else
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index c00545806bb7..2e317438980b 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -40,7 +40,7 @@ struct perf_report {
40 struct perf_tool tool; 40 struct perf_tool tool;
41 struct perf_session *session; 41 struct perf_session *session;
42 char const *input_name; 42 char const *input_name;
43 bool force, use_tui, use_stdio; 43 bool force, use_tui, use_gtk, use_stdio;
44 bool hide_unresolved; 44 bool hide_unresolved;
45 bool dont_use_callchains; 45 bool dont_use_callchains;
46 bool show_full_info; 46 bool show_full_info;
@@ -415,8 +415,13 @@ static int __cmd_report(struct perf_report *rep)
415 } 415 }
416 416
417 if (use_browser > 0) { 417 if (use_browser > 0) {
418 perf_evlist__tui_browse_hists(session->evlist, help, 418 if (use_browser == 1) {
419 NULL, NULL, 0); 419 perf_evlist__tui_browse_hists(session->evlist, help,
420 NULL, NULL, 0);
421 } else if (use_browser == 2) {
422 perf_evlist__gtk_browse_hists(session->evlist, help,
423 NULL, NULL, 0);
424 }
420 } else 425 } else
421 perf_evlist__tty_browse_hists(session->evlist, rep, help); 426 perf_evlist__tty_browse_hists(session->evlist, rep, help);
422 427
@@ -573,6 +578,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
573 OPT_STRING(0, "pretty", &report.pretty_printing_style, "key", 578 OPT_STRING(0, "pretty", &report.pretty_printing_style, "key",
574 "pretty printing style key: normal raw"), 579 "pretty printing style key: normal raw"),
575 OPT_BOOLEAN(0, "tui", &report.use_tui, "Use the TUI interface"), 580 OPT_BOOLEAN(0, "tui", &report.use_tui, "Use the TUI interface"),
581 OPT_BOOLEAN(0, "gtk", &report.use_gtk, "Use the GTK2 interface"),
576 OPT_BOOLEAN(0, "stdio", &report.use_stdio, 582 OPT_BOOLEAN(0, "stdio", &report.use_stdio,
577 "Use the stdio interface"), 583 "Use the stdio interface"),
578 OPT_STRING('s', "sort", &sort_order, "key[,key2...]", 584 OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
@@ -630,6 +636,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
630 use_browser = 0; 636 use_browser = 0;
631 else if (report.use_tui) 637 else if (report.use_tui)
632 use_browser = 1; 638 use_browser = 1;
639 else if (report.use_gtk)
640 use_browser = 2;
633 641
634 if (report.inverted_callchain) 642 if (report.inverted_callchain)
635 callchain_param.order = ORDER_CALLER; 643 callchain_param.order = ORDER_CALLER;
@@ -666,7 +674,10 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
666 } 674 }
667 675
668 if (strcmp(report.input_name, "-") != 0) { 676 if (strcmp(report.input_name, "-") != 0) {
669 setup_browser(true); 677 if (report.use_gtk)
678 perf_gtk_setup_browser(argc, argv, true);
679 else
680 setup_browser(true);
670 } else { 681 } else {
671 use_browser = 0; 682 use_browser = 0;
672 } 683 }
diff --git a/tools/perf/config/feature-tests.mak b/tools/perf/config/feature-tests.mak
index 6170fd2531b5..d9084e03ce56 100644
--- a/tools/perf/config/feature-tests.mak
+++ b/tools/perf/config/feature-tests.mak
@@ -65,6 +65,21 @@ int main(void)
65endef 65endef
66endif 66endif
67 67
68ifndef NO_GTK2
69define SOURCE_GTK2
70#pragma GCC diagnostic ignored \"-Wstrict-prototypes\"
71#include <gtk/gtk.h>
72#pragma GCC diagnostic error \"-Wstrict-prototypes\"
73
74int main(int argc, char *argv[])
75{
76 gtk_init(&argc, &argv);
77
78 return 0;
79}
80endef
81endif
82
68ifndef NO_LIBPERL 83ifndef NO_LIBPERL
69define SOURCE_PERL_EMBED 84define SOURCE_PERL_EMBED
70#include <EXTERN.h> 85#include <EXTERN.h>
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index fc5e5a09d5b9..8dd224df3e54 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -45,6 +45,18 @@ void setup_browser(bool fallback_to_pager);
45void exit_browser(bool wait_for_ok); 45void exit_browser(bool wait_for_ok);
46#endif 46#endif
47 47
48#ifdef NO_GTK2_SUPPORT
49static inline void perf_gtk_setup_browser(int argc __used, const char *argv[] __used, bool fallback_to_pager)
50{
51 if (fallback_to_pager)
52 setup_pager();
53}
54static inline void perf_gtk_exit_browser(bool wait_for_ok __used) {}
55#else
56void perf_gtk_setup_browser(int argc, const char *argv[], bool fallback_to_pager);
57void perf_gtk_exit_browser(bool wait_for_ok);
58#endif
59
48char *alias_lookup(const char *alias); 60char *alias_lookup(const char *alias);
49int split_cmdline(char *cmdline, const char ***argv); 61int split_cmdline(char *cmdline, const char ***argv);
50 62
diff --git a/tools/perf/util/gtk/browser.c b/tools/perf/util/gtk/browser.c
new file mode 100644
index 000000000000..258352a2356c
--- /dev/null
+++ b/tools/perf/util/gtk/browser.c
@@ -0,0 +1,189 @@
1#include "../evlist.h"
2#include "../cache.h"
3#include "../evsel.h"
4#include "../sort.h"
5#include "../hist.h"
6#include "gtk.h"
7
8#include <signal.h>
9
10#define MAX_COLUMNS 32
11
12void perf_gtk_setup_browser(int argc, const char *argv[],
13 bool fallback_to_pager __used)
14{
15 gtk_init(&argc, (char ***)&argv);
16}
17
18void perf_gtk_exit_browser(bool wait_for_ok __used)
19{
20 gtk_main_quit();
21}
22
23static void perf_gtk_signal(int sig)
24{
25 psignal(sig, "perf");
26 gtk_main_quit();
27}
28
29static void perf_gtk_resize_window(GtkWidget *window)
30{
31 GdkRectangle rect;
32 GdkScreen *screen;
33 int monitor;
34 int height;
35 int width;
36
37 screen = gtk_widget_get_screen(window);
38
39 monitor = gdk_screen_get_monitor_at_window(screen, window->window);
40
41 gdk_screen_get_monitor_geometry(screen, monitor, &rect);
42
43 width = rect.width * 3 / 4;
44 height = rect.height * 3 / 4;
45
46 gtk_window_resize(GTK_WINDOW(window), width, height);
47}
48
49static void perf_gtk_show_hists(GtkWidget *window, struct hists *hists)
50{
51 GType col_types[MAX_COLUMNS];
52 GtkCellRenderer *renderer;
53 struct sort_entry *se;
54 GtkListStore *store;
55 struct rb_node *nd;
56 u64 total_period;
57 GtkWidget *view;
58 int col_idx;
59 int nr_cols;
60
61 nr_cols = 0;
62
63 /* The percentage column */
64 col_types[nr_cols++] = G_TYPE_STRING;
65
66 list_for_each_entry(se, &hist_entry__sort_list, list) {
67 if (se->elide)
68 continue;
69
70 col_types[nr_cols++] = G_TYPE_STRING;
71 }
72
73 store = gtk_list_store_newv(nr_cols, col_types);
74
75 view = gtk_tree_view_new();
76
77 renderer = gtk_cell_renderer_text_new();
78
79 col_idx = 0;
80
81 /* The percentage column */
82 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
83 -1, "Overhead (%)",
84 renderer, "text",
85 col_idx++, NULL);
86
87 list_for_each_entry(se, &hist_entry__sort_list, list) {
88 if (se->elide)
89 continue;
90
91 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
92 -1, se->se_header,
93 renderer, "text",
94 col_idx++, NULL);
95 }
96
97 gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store));
98
99 g_object_unref(GTK_TREE_MODEL(store));
100
101 total_period = hists->stats.total_period;
102
103 for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
104 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
105 GtkTreeIter iter;
106 double percent;
107 char s[512];
108
109 if (h->filtered)
110 continue;
111
112 gtk_list_store_append(store, &iter);
113
114 col_idx = 0;
115
116 percent = (h->period * 100.0) / total_period;
117
118 snprintf(s, ARRAY_SIZE(s), "%.2f", percent);
119
120 gtk_list_store_set(store, &iter, col_idx++, s, -1);
121
122 list_for_each_entry(se, &hist_entry__sort_list, list) {
123 if (se->elide)
124 continue;
125
126 se->se_snprintf(h, s, ARRAY_SIZE(s),
127 hists__col_len(hists, se->se_width_idx));
128
129 gtk_list_store_set(store, &iter, col_idx++, s, -1);
130 }
131 }
132
133 gtk_container_add(GTK_CONTAINER(window), view);
134}
135
136int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
137 const char *help __used,
138 void (*timer) (void *arg)__used,
139 void *arg __used, int delay_secs __used)
140{
141 struct perf_evsel *pos;
142 GtkWidget *notebook;
143 GtkWidget *window;
144
145 signal(SIGSEGV, perf_gtk_signal);
146 signal(SIGFPE, perf_gtk_signal);
147 signal(SIGINT, perf_gtk_signal);
148 signal(SIGQUIT, perf_gtk_signal);
149 signal(SIGTERM, perf_gtk_signal);
150
151 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
152
153 gtk_window_set_title(GTK_WINDOW(window), "perf report");
154
155 g_signal_connect(window, "delete_event", gtk_main_quit, NULL);
156
157 notebook = gtk_notebook_new();
158
159 list_for_each_entry(pos, &evlist->entries, node) {
160 struct hists *hists = &pos->hists;
161 const char *evname = event_name(pos);
162 GtkWidget *scrolled_window;
163 GtkWidget *tab_label;
164
165 scrolled_window = gtk_scrolled_window_new(NULL, NULL);
166
167 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
168 GTK_POLICY_AUTOMATIC,
169 GTK_POLICY_AUTOMATIC);
170
171 perf_gtk_show_hists(scrolled_window, hists);
172
173 tab_label = gtk_label_new(evname);
174
175 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled_window, tab_label);
176 }
177
178 gtk_container_add(GTK_CONTAINER(window), notebook);
179
180 gtk_widget_show_all(window);
181
182 perf_gtk_resize_window(window);
183
184 gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
185
186 gtk_main();
187
188 return 0;
189}
diff --git a/tools/perf/util/gtk/gtk.h b/tools/perf/util/gtk/gtk.h
new file mode 100644
index 000000000000..75177ee04032
--- /dev/null
+++ b/tools/perf/util/gtk/gtk.h
@@ -0,0 +1,8 @@
1#ifndef _PERF_GTK_H_
2#define _PERF_GTK_H_ 1
3
4#pragma GCC diagnostic ignored "-Wstrict-prototypes"
5#include <gtk/gtk.h>
6#pragma GCC diagnostic error "-Wstrict-prototypes"
7
8#endif /* _PERF_GTK_H_ */
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 10343c081e19..2cae9df40e04 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -147,6 +147,23 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
147 int refresh); 147 int refresh);
148#endif 148#endif
149 149
150#ifdef NO_GTK2_SUPPORT
151static inline
152int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __used,
153 const char *help __used,
154 void(*timer)(void *arg) __used,
155 void *arg __used,
156 int refresh __used)
157{
158 return 0;
159}
160
161#else
162int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, const char *help,
163 void(*timer)(void *arg), void *arg,
164 int refresh);
165#endif
166
150unsigned int hists__sort_list_width(struct hists *self); 167unsigned int hists__sort_list_width(struct hists *self);
151 168
152#endif /* __PERF_HIST_H */ 169#endif /* __PERF_HIST_H */