aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/ui/gtk/hists.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-19 20:49:41 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-19 20:49:41 -0500
commit8f55cea410dbc56114bb71a3742032070c8108d0 (patch)
tree59605f0ee961274b22f91add33f5c32459471a83 /tools/perf/ui/gtk/hists.c
parentb7133a9a103655cda254987a3c0975fd9d8c443f (diff)
parente259514eef764a5286873618e34c560ecb6cff13 (diff)
Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf changes from Ingo Molnar: "There are lots of improvements, the biggest changes are: Main kernel side changes: - Improve uprobes performance by adding 'pre-filtering' support, by Oleg Nesterov. - Make some POWER7 events available in sysfs, equivalent to what was done on x86, from Sukadev Bhattiprolu. - tracing updates by Steve Rostedt - mostly misc fixes and smaller improvements. - Use perf/event tracing to report PCI Express advanced errors, by Tony Luck. - Enable northbridge performance counters on AMD family 15h, by Jacob Shin. - This tracing commit: tracing: Remove the extra 4 bytes of padding in events changes the ABI. All involved parties (PowerTop in particular) seem to agree that it's safe to do now with the introduction of libtraceevent, but the devil is in the details ... Main tooling side changes: - Add 'event group view', from Namyung Kim: To use it, 'perf record' should group events when recording. And then perf report parses the saved group relation from file header and prints them together if --group option is provided. You can use the 'perf evlist' command to see event group information: $ perf record -e '{ref-cycles,cycles}' noploop 1 [ perf record: Woken up 2 times to write data ] [ perf record: Captured and wrote 0.385 MB perf.data (~16807 samples) ] $ perf evlist --group {ref-cycles,cycles} With this example, default perf report will show you each event separately. You can use --group option to enable event group view: $ perf report --group ... # group: {ref-cycles,cycles} # ======== # Samples: 7K of event 'anon group { ref-cycles, cycles }' # Event count (approx.): 6876107743 # # Overhead Command Shared Object Symbol # ................ ....... ................. .......................... 99.84% 99.76% noploop noploop [.] main 0.07% 0.00% noploop ld-2.15.so [.] strcmp 0.03% 0.00% noploop [kernel.kallsyms] [k] timerqueue_del 0.03% 0.03% noploop [kernel.kallsyms] [k] sched_clock_cpu 0.02% 0.00% noploop [kernel.kallsyms] [k] account_user_time 0.01% 0.00% noploop [kernel.kallsyms] [k] __alloc_pages_nodemask 0.00% 0.00% noploop [kernel.kallsyms] [k] native_write_msr_safe 0.00% 0.11% noploop [kernel.kallsyms] [k] _raw_spin_lock 0.00% 0.06% noploop [kernel.kallsyms] [k] find_get_page 0.00% 0.02% noploop [kernel.kallsyms] [k] rcu_check_callbacks 0.00% 0.02% noploop [kernel.kallsyms] [k] __current_kernel_time As you can see the Overhead column now contains both of ref-cycles and cycles and header line shows group information also - 'anon group { ref-cycles, cycles }'. The output is sorted by period of group leader first. - Initial GTK+ annotate browser, from Namhyung Kim. - Add option for runtime switching perf data file in perf report, just press 's' and a menu with the valid files found in the current directory will be presented, from Feng Tang. - Add support to display whole group data for raw columns, from Jiri Olsa. - Add per processor socket count aggregation in perf stat, from Stephane Eranian. - Add interval printing in 'perf stat', from Stephane Eranian. - 'perf test' improvements - Add support for wildcards in tracepoint system name, from Jiri Olsa. - Add anonymous huge page recognition, from Joshua Zhu. - perf build-id cache now can show DSOs present in a perf.data file that are not in the cache, to integrate with build-id servers being put in place by organizations such as Fedora. - perf top now shares more of the evsel config/creation routines with 'record', paving the way for further integration like 'top' snapshots, etc. - perf top now supports DWARF callchains. - Fix mmap limitations on 32-bit, fix from David Miller. - 'perf bench numa mem' NUMA performance measurement suite - ... and lots of fixes, performance improvements, cleanups and other improvements I failed to list - see the shortlog and git log for details." * 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (270 commits) perf/x86/amd: Enable northbridge performance counters on AMD family 15h perf/hwbp: Fix cleanup in case of kzalloc failure perf tools: Fix build with bison 2.3 and older. perf tools: Limit unwind support to x86 archs perf annotate: Make it to be able to skip unannotatable symbols perf gtk/annotate: Fail early if it can't annotate perf gtk/annotate: Show source lines with gray color perf gtk/annotate: Support multiple event annotation perf ui/gtk: Implement basic GTK2 annotation browser perf annotate: Fix warning message on a missing vmlinux perf buildid-cache: Add --update option uprobes/perf: Avoid uprobe_apply() whenever possible uprobes/perf: Teach trace_uprobe/perf code to use UPROBE_HANDLER_REMOVE uprobes/perf: Teach trace_uprobe/perf code to pre-filter uprobes/perf: Teach trace_uprobe/perf code to track the active perf_event's uprobes: Introduce uprobe_apply() perf: Introduce hw_perf_event->tp_target and ->tp_list uprobes/perf: Always increment trace_uprobe->nhit uprobes/tracing: Kill uprobe_trace_consumer, embed uprobe_consumer into trace_uprobe uprobes/tracing: Introduce is_trace_uprobe_enabled() ...
Diffstat (limited to 'tools/perf/ui/gtk/hists.c')
-rw-r--r--tools/perf/ui/gtk/hists.c312
1 files changed, 312 insertions, 0 deletions
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
new file mode 100644
index 000000000000..1e764a8ad259
--- /dev/null
+++ b/tools/perf/ui/gtk/hists.c
@@ -0,0 +1,312 @@
1#include "../evlist.h"
2#include "../cache.h"
3#include "../evsel.h"
4#include "../sort.h"
5#include "../hist.h"
6#include "../helpline.h"
7#include "gtk.h"
8
9#define MAX_COLUMNS 32
10
11static int __percent_color_snprintf(char *buf, size_t size, double percent)
12{
13 int ret = 0;
14 const char *markup;
15
16 markup = perf_gtk__get_percent_color(percent);
17 if (markup)
18 ret += scnprintf(buf, size, markup);
19
20 ret += scnprintf(buf + ret, size - ret, " %6.2f%%", percent);
21
22 if (markup)
23 ret += scnprintf(buf + ret, size - ret, "</span>");
24
25 return ret;
26}
27
28
29static int __hpp__color_fmt(struct perf_hpp *hpp, struct hist_entry *he,
30 u64 (*get_field)(struct hist_entry *))
31{
32 int ret;
33 double percent = 0.0;
34 struct hists *hists = he->hists;
35
36 if (hists->stats.total_period)
37 percent = 100.0 * get_field(he) / hists->stats.total_period;
38
39 ret = __percent_color_snprintf(hpp->buf, hpp->size, percent);
40
41 if (symbol_conf.event_group) {
42 int prev_idx, idx_delta;
43 struct perf_evsel *evsel = hists_to_evsel(hists);
44 struct hist_entry *pair;
45 int nr_members = evsel->nr_members;
46
47 if (nr_members <= 1)
48 return ret;
49
50 prev_idx = perf_evsel__group_idx(evsel);
51
52 list_for_each_entry(pair, &he->pairs.head, pairs.node) {
53 u64 period = get_field(pair);
54 u64 total = pair->hists->stats.total_period;
55
56 evsel = hists_to_evsel(pair->hists);
57 idx_delta = perf_evsel__group_idx(evsel) - prev_idx - 1;
58
59 while (idx_delta--) {
60 /*
61 * zero-fill group members in the middle which
62 * have no sample
63 */
64 ret += __percent_color_snprintf(hpp->buf + ret,
65 hpp->size - ret,
66 0.0);
67 }
68
69 percent = 100.0 * period / total;
70 ret += __percent_color_snprintf(hpp->buf + ret,
71 hpp->size - ret,
72 percent);
73
74 prev_idx = perf_evsel__group_idx(evsel);
75 }
76
77 idx_delta = nr_members - prev_idx - 1;
78
79 while (idx_delta--) {
80 /*
81 * zero-fill group members at last which have no sample
82 */
83 ret += __percent_color_snprintf(hpp->buf + ret,
84 hpp->size - ret,
85 0.0);
86 }
87 }
88 return ret;
89}
90
91#define __HPP_COLOR_PERCENT_FN(_type, _field) \
92static u64 he_get_##_field(struct hist_entry *he) \
93{ \
94 return he->stat._field; \
95} \
96 \
97static int perf_gtk__hpp_color_##_type(struct perf_hpp *hpp, \
98 struct hist_entry *he) \
99{ \
100 return __hpp__color_fmt(hpp, he, he_get_##_field); \
101}
102
103__HPP_COLOR_PERCENT_FN(overhead, period)
104__HPP_COLOR_PERCENT_FN(overhead_sys, period_sys)
105__HPP_COLOR_PERCENT_FN(overhead_us, period_us)
106__HPP_COLOR_PERCENT_FN(overhead_guest_sys, period_guest_sys)
107__HPP_COLOR_PERCENT_FN(overhead_guest_us, period_guest_us)
108
109#undef __HPP_COLOR_PERCENT_FN
110
111
112void perf_gtk__init_hpp(void)
113{
114 perf_hpp__column_enable(PERF_HPP__OVERHEAD);
115
116 perf_hpp__init();
117
118 perf_hpp__format[PERF_HPP__OVERHEAD].color =
119 perf_gtk__hpp_color_overhead;
120 perf_hpp__format[PERF_HPP__OVERHEAD_SYS].color =
121 perf_gtk__hpp_color_overhead_sys;
122 perf_hpp__format[PERF_HPP__OVERHEAD_US].color =
123 perf_gtk__hpp_color_overhead_us;
124 perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_SYS].color =
125 perf_gtk__hpp_color_overhead_guest_sys;
126 perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_US].color =
127 perf_gtk__hpp_color_overhead_guest_us;
128}
129
130static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
131{
132 struct perf_hpp_fmt *fmt;
133 GType col_types[MAX_COLUMNS];
134 GtkCellRenderer *renderer;
135 struct sort_entry *se;
136 GtkListStore *store;
137 struct rb_node *nd;
138 GtkWidget *view;
139 int col_idx;
140 int nr_cols;
141 char s[512];
142
143 struct perf_hpp hpp = {
144 .buf = s,
145 .size = sizeof(s),
146 .ptr = hists_to_evsel(hists),
147 };
148
149 nr_cols = 0;
150
151 perf_hpp__for_each_format(fmt)
152 col_types[nr_cols++] = G_TYPE_STRING;
153
154 list_for_each_entry(se, &hist_entry__sort_list, list) {
155 if (se->elide)
156 continue;
157
158 col_types[nr_cols++] = G_TYPE_STRING;
159 }
160
161 store = gtk_list_store_newv(nr_cols, col_types);
162
163 view = gtk_tree_view_new();
164
165 renderer = gtk_cell_renderer_text_new();
166
167 col_idx = 0;
168
169 perf_hpp__for_each_format(fmt) {
170 fmt->header(&hpp);
171
172 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
173 -1, ltrim(s),
174 renderer, "markup",
175 col_idx++, NULL);
176 }
177
178 list_for_each_entry(se, &hist_entry__sort_list, list) {
179 if (se->elide)
180 continue;
181
182 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
183 -1, se->se_header,
184 renderer, "text",
185 col_idx++, NULL);
186 }
187
188 gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store));
189
190 g_object_unref(GTK_TREE_MODEL(store));
191
192 for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
193 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
194 GtkTreeIter iter;
195
196 if (h->filtered)
197 continue;
198
199 gtk_list_store_append(store, &iter);
200
201 col_idx = 0;
202
203 perf_hpp__for_each_format(fmt) {
204 if (fmt->color)
205 fmt->color(&hpp, h);
206 else
207 fmt->entry(&hpp, h);
208
209 gtk_list_store_set(store, &iter, col_idx++, s, -1);
210 }
211
212 list_for_each_entry(se, &hist_entry__sort_list, list) {
213 if (se->elide)
214 continue;
215
216 se->se_snprintf(h, s, ARRAY_SIZE(s),
217 hists__col_len(hists, se->se_width_idx));
218
219 gtk_list_store_set(store, &iter, col_idx++, s, -1);
220 }
221 }
222
223 gtk_container_add(GTK_CONTAINER(window), view);
224}
225
226int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
227 const char *help,
228 struct hist_browser_timer *hbt __maybe_unused)
229{
230 struct perf_evsel *pos;
231 GtkWidget *vbox;
232 GtkWidget *notebook;
233 GtkWidget *info_bar;
234 GtkWidget *statbar;
235 GtkWidget *window;
236
237 signal(SIGSEGV, perf_gtk__signal);
238 signal(SIGFPE, perf_gtk__signal);
239 signal(SIGINT, perf_gtk__signal);
240 signal(SIGQUIT, perf_gtk__signal);
241 signal(SIGTERM, perf_gtk__signal);
242
243 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
244
245 gtk_window_set_title(GTK_WINDOW(window), "perf report");
246
247 g_signal_connect(window, "delete_event", gtk_main_quit, NULL);
248
249 pgctx = perf_gtk__activate_context(window);
250 if (!pgctx)
251 return -1;
252
253 vbox = gtk_vbox_new(FALSE, 0);
254
255 notebook = gtk_notebook_new();
256
257 gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0);
258
259 info_bar = perf_gtk__setup_info_bar();
260 if (info_bar)
261 gtk_box_pack_start(GTK_BOX(vbox), info_bar, FALSE, FALSE, 0);
262
263 statbar = perf_gtk__setup_statusbar();
264 gtk_box_pack_start(GTK_BOX(vbox), statbar, FALSE, FALSE, 0);
265
266 gtk_container_add(GTK_CONTAINER(window), vbox);
267
268 list_for_each_entry(pos, &evlist->entries, node) {
269 struct hists *hists = &pos->hists;
270 const char *evname = perf_evsel__name(pos);
271 GtkWidget *scrolled_window;
272 GtkWidget *tab_label;
273 char buf[512];
274 size_t size = sizeof(buf);
275
276 if (symbol_conf.event_group) {
277 if (!perf_evsel__is_group_leader(pos))
278 continue;
279
280 if (pos->nr_members > 1) {
281 perf_evsel__group_desc(pos, buf, size);
282 evname = buf;
283 }
284 }
285
286 scrolled_window = gtk_scrolled_window_new(NULL, NULL);
287
288 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
289 GTK_POLICY_AUTOMATIC,
290 GTK_POLICY_AUTOMATIC);
291
292 perf_gtk__show_hists(scrolled_window, hists);
293
294 tab_label = gtk_label_new(evname);
295
296 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled_window, tab_label);
297 }
298
299 gtk_widget_show_all(window);
300
301 perf_gtk__resize_window(window);
302
303 gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
304
305 ui_helpline__push(help);
306
307 gtk_main();
308
309 perf_gtk__deactivate_context(&pgctx);
310
311 return 0;
312}