aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
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/perf/util
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/perf/util')
-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
4 files changed, 226 insertions, 0 deletions
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 */