From 2b676bf068916046151277f27113f80828e33001 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 7 Feb 2013 18:02:08 +0900 Subject: perf ui/gtk: Implement basic GTK2 annotation browser Basic implementation of perf annotate on GTK2. Currently only shows first symbol. Add a new --gtk option to use it. Signed-off-by: Namhyung Kim Cc: Andi Kleen Cc: Borislav Petkov Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Pekka Enberg Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1360227734-375-2-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/gtk/annotate.c | 185 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 tools/perf/ui/gtk/annotate.c (limited to 'tools/perf/ui/gtk/annotate.c') diff --git a/tools/perf/ui/gtk/annotate.c b/tools/perf/ui/gtk/annotate.c new file mode 100644 index 00000000000..19d84fa327a --- /dev/null +++ b/tools/perf/ui/gtk/annotate.c @@ -0,0 +1,185 @@ +#include "gtk.h" +#include "util/debug.h" +#include "util/annotate.h" +#include "ui/helpline.h" + + +enum { + ANN_COL__PERCENT, + ANN_COL__OFFSET, + ANN_COL__LINE, + + MAX_ANN_COLS +}; + +static const char *const col_names[] = { + "Overhead", + "Offset", + "Line" +}; + +static int perf_gtk__get_percent(char *buf, size_t size, struct symbol *sym, + struct disasm_line *dl, int evidx) +{ + struct sym_hist *symhist; + double percent = 0.0; + const char *markup; + int ret = 0; + + strcpy(buf, ""); + + if (dl->offset == (s64) -1) + return 0; + + symhist = annotation__histogram(symbol__annotation(sym), evidx); + if (!symhist->addr[dl->offset]) + return 0; + + percent = 100.0 * symhist->addr[dl->offset] / symhist->sum; + + markup = perf_gtk__get_percent_color(percent); + if (markup) + ret += scnprintf(buf, size, "%s", markup); + ret += scnprintf(buf + ret, size - ret, "%6.2f%%", percent); + if (markup) + ret += scnprintf(buf + ret, size - ret, ""); + + return ret; +} + +static int perf_gtk__get_offset(char *buf, size_t size, struct symbol *sym, + struct map *map, struct disasm_line *dl) +{ + u64 start = map__rip_2objdump(map, sym->start); + + strcpy(buf, ""); + + if (dl->offset == (s64) -1) + return 0; + + return scnprintf(buf, size, "%"PRIx64, start + dl->offset); +} + +static int perf_gtk__annotate_symbol(GtkWidget *window, struct symbol *sym, + struct map *map, int evidx, + struct hist_browser_timer *hbt __maybe_unused) +{ + struct disasm_line *pos, *n; + struct annotation *notes; + GType col_types[MAX_ANN_COLS]; + GtkCellRenderer *renderer; + GtkListStore *store; + GtkWidget *view; + int i; + char s[512]; + + if (map->dso->annotate_warned) + return -1; + + if (symbol__annotate(sym, map, 0) < 0) { + ui__error("%s", ui_helpline__current); + return -1; + } + + notes = symbol__annotation(sym); + + for (i = 0; i < MAX_ANN_COLS; i++) { + col_types[i] = G_TYPE_STRING; + } + store = gtk_list_store_newv(MAX_ANN_COLS, col_types); + + view = gtk_tree_view_new(); + renderer = gtk_cell_renderer_text_new(); + + for (i = 0; i < MAX_ANN_COLS; i++) { + gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), + -1, col_names[i], renderer, + i == ANN_COL__PERCENT ? "markup" : "text", + i, NULL); + } + + gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store)); + g_object_unref(GTK_TREE_MODEL(store)); + + list_for_each_entry(pos, ¬es->src->source, node) { + GtkTreeIter iter; + + gtk_list_store_append(store, &iter); + + if (perf_gtk__get_percent(s, sizeof(s), sym, pos, evidx)) + gtk_list_store_set(store, &iter, ANN_COL__PERCENT, s, -1); + if (perf_gtk__get_offset(s, sizeof(s), sym, map, pos)) + gtk_list_store_set(store, &iter, ANN_COL__OFFSET, s, -1); + gtk_list_store_set(store, &iter, ANN_COL__LINE, pos->line, -1); + } + + gtk_container_add(GTK_CONTAINER(window), view); + + list_for_each_entry_safe(pos, n, ¬es->src->source, node) { + list_del(&pos->node); + disasm_line__free(pos); + } + + return 0; +} + +int symbol__gtk_annotate(struct symbol *sym, struct map *map, int evidx, + struct hist_browser_timer *hbt) +{ + GtkWidget *vbox; + GtkWidget *notebook; + GtkWidget *infobar; + GtkWidget *statbar; + GtkWidget *window; + GtkWidget *scrolled_window; + GtkWidget *tab_label; + + signal(SIGSEGV, perf_gtk__signal); + signal(SIGFPE, perf_gtk__signal); + signal(SIGINT, perf_gtk__signal); + signal(SIGQUIT, perf_gtk__signal); + signal(SIGTERM, perf_gtk__signal); + + window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_title(GTK_WINDOW(window), "perf annotate"); + + g_signal_connect(window, "delete_event", gtk_main_quit, NULL); + + pgctx = perf_gtk__activate_context(window); + if (!pgctx) + return -1; + + vbox = gtk_vbox_new(FALSE, 0); + notebook = gtk_notebook_new(); + scrolled_window = gtk_scrolled_window_new(NULL, NULL); + tab_label = gtk_label_new(sym->name); + + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled_window, + tab_label); + gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0); + + infobar = perf_gtk__setup_info_bar(); + if (infobar) + gtk_box_pack_start(GTK_BOX(vbox), infobar, FALSE, FALSE, 0); + + statbar = perf_gtk__setup_statusbar(); + gtk_box_pack_start(GTK_BOX(vbox), statbar, FALSE, FALSE, 0); + + gtk_container_add(GTK_CONTAINER(window), vbox); + + perf_gtk__annotate_symbol(scrolled_window, sym, map, evidx, hbt); + + gtk_widget_show_all(window); + + perf_gtk__resize_window(window); + gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); + + gtk_main(); + + perf_gtk__deactivate_context(&pgctx); + return 0; +} -- cgit v1.2.3-70-g09d2 From 7a60ba948267336d77a48a3539f98151f9dcfba6 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 7 Feb 2013 18:02:09 +0900 Subject: perf gtk/annotate: Support multiple event annotation Show multiple annotation result for each evsel. Each result represents the most frquently sampled symbol/function for the evsel and it will be shown in a tab window. For this add a reference to main container (notebook) to the pgctx. At the first call to annotate browser, hist_entry__find_annotations() will setup a new browser, and next calls will add new tabs to the browser. But it requires final perf_gtk__show_annotations() to start processing GUI events. Signed-off-by: Namhyung Kim Cc: Andi Kleen Cc: Borislav Petkov Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Pekka Enberg Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1360227734-375-3-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-annotate.c | 4 +++ tools/perf/ui/gtk/annotate.c | 74 +++++++++++++++++++++++++++---------------- tools/perf/ui/gtk/gtk.h | 1 + tools/perf/util/annotate.h | 4 +++ 4 files changed, 56 insertions(+), 27 deletions(-) (limited to 'tools/perf/ui/gtk/annotate.c') diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 9d758c9611a..68e3a16abd3 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -227,6 +227,10 @@ static int __cmd_annotate(struct perf_annotate *ann) ui__error("The %s file has no samples!\n", session->filename); goto out_delete; } + + if (use_browser == 2) + perf_gtk__show_annotations(); + out_delete: /* * Speed up the exit process, for large files this can diff --git a/tools/perf/ui/gtk/annotate.c b/tools/perf/ui/gtk/annotate.c index 19d84fa327a..1ce89f2558f 100644 --- a/tools/perf/ui/gtk/annotate.c +++ b/tools/perf/ui/gtk/annotate.c @@ -126,31 +126,52 @@ static int perf_gtk__annotate_symbol(GtkWidget *window, struct symbol *sym, int symbol__gtk_annotate(struct symbol *sym, struct map *map, int evidx, struct hist_browser_timer *hbt) { - GtkWidget *vbox; - GtkWidget *notebook; - GtkWidget *infobar; - GtkWidget *statbar; GtkWidget *window; + GtkWidget *notebook; GtkWidget *scrolled_window; GtkWidget *tab_label; - signal(SIGSEGV, perf_gtk__signal); - signal(SIGFPE, perf_gtk__signal); - signal(SIGINT, perf_gtk__signal); - signal(SIGQUIT, perf_gtk__signal); - signal(SIGTERM, perf_gtk__signal); + if (perf_gtk__is_active_context(pgctx)) { + window = pgctx->main_window; + notebook = pgctx->notebook; + } else { + GtkWidget *vbox; + GtkWidget *infobar; + GtkWidget *statbar; - window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_title(GTK_WINDOW(window), "perf annotate"); + signal(SIGSEGV, perf_gtk__signal); + signal(SIGFPE, perf_gtk__signal); + signal(SIGINT, perf_gtk__signal); + signal(SIGQUIT, perf_gtk__signal); + signal(SIGTERM, perf_gtk__signal); - g_signal_connect(window, "delete_event", gtk_main_quit, NULL); + window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_title(GTK_WINDOW(window), "perf annotate"); - pgctx = perf_gtk__activate_context(window); - if (!pgctx) - return -1; + g_signal_connect(window, "delete_event", gtk_main_quit, NULL); + + pgctx = perf_gtk__activate_context(window); + if (!pgctx) + return -1; + + vbox = gtk_vbox_new(FALSE, 0); + notebook = gtk_notebook_new(); + pgctx->notebook = notebook; + + gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0); + + infobar = perf_gtk__setup_info_bar(); + if (infobar) { + gtk_box_pack_start(GTK_BOX(vbox), infobar, + FALSE, FALSE, 0); + } + + statbar = perf_gtk__setup_statusbar(); + gtk_box_pack_start(GTK_BOX(vbox), statbar, FALSE, FALSE, 0); + + gtk_container_add(GTK_CONTAINER(window), vbox); + } - vbox = gtk_vbox_new(FALSE, 0); - notebook = gtk_notebook_new(); scrolled_window = gtk_scrolled_window_new(NULL, NULL); tab_label = gtk_label_new(sym->name); @@ -160,19 +181,19 @@ int symbol__gtk_annotate(struct symbol *sym, struct map *map, int evidx, gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled_window, tab_label); - gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0); - - infobar = perf_gtk__setup_info_bar(); - if (infobar) - gtk_box_pack_start(GTK_BOX(vbox), infobar, FALSE, FALSE, 0); - statbar = perf_gtk__setup_statusbar(); - gtk_box_pack_start(GTK_BOX(vbox), statbar, FALSE, FALSE, 0); + perf_gtk__annotate_symbol(scrolled_window, sym, map, evidx, hbt); + return 0; +} - gtk_container_add(GTK_CONTAINER(window), vbox); +void perf_gtk__show_annotations(void) +{ + GtkWidget *window; - perf_gtk__annotate_symbol(scrolled_window, sym, map, evidx, hbt); + if (!perf_gtk__is_active_context(pgctx)) + return; + window = pgctx->main_window; gtk_widget_show_all(window); perf_gtk__resize_window(window); @@ -181,5 +202,4 @@ int symbol__gtk_annotate(struct symbol *sym, struct map *map, int evidx, gtk_main(); perf_gtk__deactivate_context(&pgctx); - return 0; } diff --git a/tools/perf/ui/gtk/gtk.h b/tools/perf/ui/gtk/gtk.h index 5d369375482..3d96785ef15 100644 --- a/tools/perf/ui/gtk/gtk.h +++ b/tools/perf/ui/gtk/gtk.h @@ -10,6 +10,7 @@ struct perf_gtk_context { GtkWidget *main_window; + GtkWidget *notebook; #ifdef HAVE_GTK_INFO_BAR GtkWidget *info_bar; diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index a8ccbda4aeb..c422440fe61 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -164,6 +164,8 @@ static inline int hist_entry__gtk_annotate(struct hist_entry *he, int evidx, { return symbol__gtk_annotate(he->ms.sym, he->ms.map, evidx, hbt); } + +void perf_gtk__show_annotations(void); #else static inline int hist_entry__gtk_annotate(struct hist_entry *he __maybe_unused, int evidx __maybe_unused, @@ -172,6 +174,8 @@ static inline int hist_entry__gtk_annotate(struct hist_entry *he __maybe_unused, { return 0; } + +static inline void perf_gtk__show_annotations(void) {} #endif extern const char *disassembler_style; -- cgit v1.2.3-70-g09d2 From 237522378604a2e26e19a8b11a70171eaf98c6c5 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 7 Feb 2013 18:02:10 +0900 Subject: perf gtk/annotate: Show source lines with gray color In order to differentiate source lines from asm line, print them with gray color. To do this, it needs to be escaped since sometimes it contains "<" and/or ">" characters so that it should not be considered as a markup tags. Use glib's g_markup_escape_text() for this. Signed-off-by: Namhyung Kim Cc: Andi Kleen Cc: Borislav Petkov Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Pekka Enberg Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1360227734-375-4-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/gtk/annotate.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) (limited to 'tools/perf/ui/gtk/annotate.c') diff --git a/tools/perf/ui/gtk/annotate.c b/tools/perf/ui/gtk/annotate.c index 1ce89f2558f..2fe056b0096 100644 --- a/tools/perf/ui/gtk/annotate.c +++ b/tools/perf/ui/gtk/annotate.c @@ -60,6 +60,30 @@ static int perf_gtk__get_offset(char *buf, size_t size, struct symbol *sym, return scnprintf(buf, size, "%"PRIx64, start + dl->offset); } +static int perf_gtk__get_line(char *buf, size_t size, struct disasm_line *dl) +{ + int ret = 0; + char *line = g_markup_escape_text(dl->line, -1); + const char *markup = ""; + + strcpy(buf, ""); + + if (!line) + return 0; + + if (dl->offset != (s64) -1) + markup = NULL; + + if (markup) + ret += scnprintf(buf, size, "%s", markup); + ret += scnprintf(buf + ret, size - ret, "%s", line); + if (markup) + ret += scnprintf(buf + ret, size - ret, ""); + + g_free(line); + return ret; +} + static int perf_gtk__annotate_symbol(GtkWidget *window, struct symbol *sym, struct map *map, int evidx, struct hist_browser_timer *hbt __maybe_unused) @@ -93,8 +117,7 @@ static int perf_gtk__annotate_symbol(GtkWidget *window, struct symbol *sym, for (i = 0; i < MAX_ANN_COLS; i++) { gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), - -1, col_names[i], renderer, - i == ANN_COL__PERCENT ? "markup" : "text", + -1, col_names[i], renderer, "markup", i, NULL); } @@ -110,7 +133,8 @@ static int perf_gtk__annotate_symbol(GtkWidget *window, struct symbol *sym, gtk_list_store_set(store, &iter, ANN_COL__PERCENT, s, -1); if (perf_gtk__get_offset(s, sizeof(s), sym, map, pos)) gtk_list_store_set(store, &iter, ANN_COL__OFFSET, s, -1); - gtk_list_store_set(store, &iter, ANN_COL__LINE, pos->line, -1); + if (perf_gtk__get_line(s, sizeof(s), pos)) + gtk_list_store_set(store, &iter, ANN_COL__LINE, s, -1); } gtk_container_add(GTK_CONTAINER(window), view); -- cgit v1.2.3-70-g09d2 From c0e79be74907b4654b622601692e1a27fd1dbeb3 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 7 Feb 2013 18:02:13 +0900 Subject: perf gtk/annotate: Fail early if it can't annotate Don't need to setup a browser window if annotate cannot work. Signed-off-by: Namhyung Kim Cc: Andi Kleen Cc: Borislav Petkov Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Pekka Enberg Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1360227734-375-7-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/gtk/annotate.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'tools/perf/ui/gtk/annotate.c') diff --git a/tools/perf/ui/gtk/annotate.c b/tools/perf/ui/gtk/annotate.c index 2fe056b0096..7d8dc581a54 100644 --- a/tools/perf/ui/gtk/annotate.c +++ b/tools/perf/ui/gtk/annotate.c @@ -97,14 +97,6 @@ static int perf_gtk__annotate_symbol(GtkWidget *window, struct symbol *sym, int i; char s[512]; - if (map->dso->annotate_warned) - return -1; - - if (symbol__annotate(sym, map, 0) < 0) { - ui__error("%s", ui_helpline__current); - return -1; - } - notes = symbol__annotation(sym); for (i = 0; i < MAX_ANN_COLS; i++) { @@ -155,6 +147,14 @@ int symbol__gtk_annotate(struct symbol *sym, struct map *map, int evidx, GtkWidget *scrolled_window; GtkWidget *tab_label; + if (map->dso->annotate_warned) + return -1; + + if (symbol__annotate(sym, map, 0) < 0) { + ui__error("%s", ui_helpline__current); + return -1; + } + if (perf_gtk__is_active_context(pgctx)) { window = pgctx->main_window; notebook = pgctx->notebook; -- cgit v1.2.3-70-g09d2