aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/ui/gtk/annotate.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/annotate.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/annotate.c')
-rw-r--r--tools/perf/ui/gtk/annotate.c229
1 files changed, 229 insertions, 0 deletions
diff --git a/tools/perf/ui/gtk/annotate.c b/tools/perf/ui/gtk/annotate.c
new file mode 100644
index 000000000000..7d8dc581a545
--- /dev/null
+++ b/tools/perf/ui/gtk/annotate.c
@@ -0,0 +1,229 @@
1#include "gtk.h"
2#include "util/debug.h"
3#include "util/annotate.h"
4#include "ui/helpline.h"
5
6
7enum {
8 ANN_COL__PERCENT,
9 ANN_COL__OFFSET,
10 ANN_COL__LINE,
11
12 MAX_ANN_COLS
13};
14
15static const char *const col_names[] = {
16 "Overhead",
17 "Offset",
18 "Line"
19};
20
21static int perf_gtk__get_percent(char *buf, size_t size, struct symbol *sym,
22 struct disasm_line *dl, int evidx)
23{
24 struct sym_hist *symhist;
25 double percent = 0.0;
26 const char *markup;
27 int ret = 0;
28
29 strcpy(buf, "");
30
31 if (dl->offset == (s64) -1)
32 return 0;
33
34 symhist = annotation__histogram(symbol__annotation(sym), evidx);
35 if (!symhist->addr[dl->offset])
36 return 0;
37
38 percent = 100.0 * symhist->addr[dl->offset] / symhist->sum;
39
40 markup = perf_gtk__get_percent_color(percent);
41 if (markup)
42 ret += scnprintf(buf, size, "%s", markup);
43 ret += scnprintf(buf + ret, size - ret, "%6.2f%%", percent);
44 if (markup)
45 ret += scnprintf(buf + ret, size - ret, "</span>");
46
47 return ret;
48}
49
50static int perf_gtk__get_offset(char *buf, size_t size, struct symbol *sym,
51 struct map *map, struct disasm_line *dl)
52{
53 u64 start = map__rip_2objdump(map, sym->start);
54
55 strcpy(buf, "");
56
57 if (dl->offset == (s64) -1)
58 return 0;
59
60 return scnprintf(buf, size, "%"PRIx64, start + dl->offset);
61}
62
63static int perf_gtk__get_line(char *buf, size_t size, struct disasm_line *dl)
64{
65 int ret = 0;
66 char *line = g_markup_escape_text(dl->line, -1);
67 const char *markup = "<span fgcolor='gray'>";
68
69 strcpy(buf, "");
70
71 if (!line)
72 return 0;
73
74 if (dl->offset != (s64) -1)
75 markup = NULL;
76
77 if (markup)
78 ret += scnprintf(buf, size, "%s", markup);
79 ret += scnprintf(buf + ret, size - ret, "%s", line);
80 if (markup)
81 ret += scnprintf(buf + ret, size - ret, "</span>");
82
83 g_free(line);
84 return ret;
85}
86
87static int perf_gtk__annotate_symbol(GtkWidget *window, struct symbol *sym,
88 struct map *map, int evidx,
89 struct hist_browser_timer *hbt __maybe_unused)
90{
91 struct disasm_line *pos, *n;
92 struct annotation *notes;
93 GType col_types[MAX_ANN_COLS];
94 GtkCellRenderer *renderer;
95 GtkListStore *store;
96 GtkWidget *view;
97 int i;
98 char s[512];
99
100 notes = symbol__annotation(sym);
101
102 for (i = 0; i < MAX_ANN_COLS; i++) {
103 col_types[i] = G_TYPE_STRING;
104 }
105 store = gtk_list_store_newv(MAX_ANN_COLS, col_types);
106
107 view = gtk_tree_view_new();
108 renderer = gtk_cell_renderer_text_new();
109
110 for (i = 0; i < MAX_ANN_COLS; i++) {
111 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
112 -1, col_names[i], renderer, "markup",
113 i, NULL);
114 }
115
116 gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store));
117 g_object_unref(GTK_TREE_MODEL(store));
118
119 list_for_each_entry(pos, &notes->src->source, node) {
120 GtkTreeIter iter;
121
122 gtk_list_store_append(store, &iter);
123
124 if (perf_gtk__get_percent(s, sizeof(s), sym, pos, evidx))
125 gtk_list_store_set(store, &iter, ANN_COL__PERCENT, s, -1);
126 if (perf_gtk__get_offset(s, sizeof(s), sym, map, pos))
127 gtk_list_store_set(store, &iter, ANN_COL__OFFSET, s, -1);
128 if (perf_gtk__get_line(s, sizeof(s), pos))
129 gtk_list_store_set(store, &iter, ANN_COL__LINE, s, -1);
130 }
131
132 gtk_container_add(GTK_CONTAINER(window), view);
133
134 list_for_each_entry_safe(pos, n, &notes->src->source, node) {
135 list_del(&pos->node);
136 disasm_line__free(pos);
137 }
138
139 return 0;
140}
141
142int symbol__gtk_annotate(struct symbol *sym, struct map *map, int evidx,
143 struct hist_browser_timer *hbt)
144{
145 GtkWidget *window;
146 GtkWidget *notebook;
147 GtkWidget *scrolled_window;
148 GtkWidget *tab_label;
149
150 if (map->dso->annotate_warned)
151 return -1;
152
153 if (symbol__annotate(sym, map, 0) < 0) {
154 ui__error("%s", ui_helpline__current);
155 return -1;
156 }
157
158 if (perf_gtk__is_active_context(pgctx)) {
159 window = pgctx->main_window;
160 notebook = pgctx->notebook;
161 } else {
162 GtkWidget *vbox;
163 GtkWidget *infobar;
164 GtkWidget *statbar;
165
166 signal(SIGSEGV, perf_gtk__signal);
167 signal(SIGFPE, perf_gtk__signal);
168 signal(SIGINT, perf_gtk__signal);
169 signal(SIGQUIT, perf_gtk__signal);
170 signal(SIGTERM, perf_gtk__signal);
171
172 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
173 gtk_window_set_title(GTK_WINDOW(window), "perf annotate");
174
175 g_signal_connect(window, "delete_event", gtk_main_quit, NULL);
176
177 pgctx = perf_gtk__activate_context(window);
178 if (!pgctx)
179 return -1;
180
181 vbox = gtk_vbox_new(FALSE, 0);
182 notebook = gtk_notebook_new();
183 pgctx->notebook = notebook;
184
185 gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0);
186
187 infobar = perf_gtk__setup_info_bar();
188 if (infobar) {
189 gtk_box_pack_start(GTK_BOX(vbox), infobar,
190 FALSE, FALSE, 0);
191 }
192
193 statbar = perf_gtk__setup_statusbar();
194 gtk_box_pack_start(GTK_BOX(vbox), statbar, FALSE, FALSE, 0);
195
196 gtk_container_add(GTK_CONTAINER(window), vbox);
197 }
198
199 scrolled_window = gtk_scrolled_window_new(NULL, NULL);
200 tab_label = gtk_label_new(sym->name);
201
202 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
203 GTK_POLICY_AUTOMATIC,
204 GTK_POLICY_AUTOMATIC);
205
206 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled_window,
207 tab_label);
208
209 perf_gtk__annotate_symbol(scrolled_window, sym, map, evidx, hbt);
210 return 0;
211}
212
213void perf_gtk__show_annotations(void)
214{
215 GtkWidget *window;
216
217 if (!perf_gtk__is_active_context(pgctx))
218 return;
219
220 window = pgctx->main_window;
221 gtk_widget_show_all(window);
222
223 perf_gtk__resize_window(window);
224 gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
225
226 gtk_main();
227
228 perf_gtk__deactivate_context(&pgctx);
229}