Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2b676bf0 authored by Namhyung Kim's avatar Namhyung Kim Committed by Arnaldo Carvalho de Melo
Browse files

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: default avatarNamhyung Kim <namhyung@kernel.org>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung.kim@lge.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1360227734-375-2-git-send-email-namhyung@kernel.org


Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent e3a34029
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -61,11 +61,13 @@ OPTIONS

--stdio:: Use the stdio interface.

--tui:: Use the TUI interface Use of --tui requires a tty, if one is not
--tui:: Use the TUI interface. Use of --tui requires a tty, if one is not
	present, as when piping to other commands, the stdio interface is
	used. This interfaces starts by centering on the line with more
	samples, TAB/UNTAB cycles through the lines with more samples.

--gtk:: Use the GTK interface.

-C::
--cpu:: Only report samples for the list of CPUs provided. Multiple CPUs can
	be provided as a comma-separated list with no space: 0,1. Ranges of
+1 −0
Original line number Diff line number Diff line
@@ -698,6 +698,7 @@ ifndef NO_GTK2
		LIB_OBJS += $(OUTPUT)ui/gtk/util.o
		LIB_OBJS += $(OUTPUT)ui/gtk/helpline.o
		LIB_OBJS += $(OUTPUT)ui/gtk/progress.o
		LIB_OBJS += $(OUTPUT)ui/gtk/annotate.o
	endif
endif

+8 −2
Original line number Diff line number Diff line
@@ -34,7 +34,7 @@

struct perf_annotate {
	struct perf_tool tool;
	bool	   force, use_tui, use_stdio;
	bool	   force, use_tui, use_stdio, use_gtk;
	bool	   full_paths;
	bool	   print_line;
	const char *sym_hist_filter;
@@ -138,7 +138,10 @@ static void hists__find_annotations(struct hists *self, int evidx,
			continue;
		}

		if (use_browser > 0) {
		if (use_browser == 2) {
			hist_entry__gtk_annotate(he, evidx, NULL);
			return;
		} else if (use_browser == 1) {
			key = hist_entry__tui_annotate(he, evidx, NULL);
			switch (key) {
			case K_RIGHT:
@@ -270,6 +273,7 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
		    "be more verbose (show symbol address, etc)"),
	OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
		    "dump raw trace in ASCII"),
	OPT_BOOLEAN(0, "gtk", &annotate.use_gtk, "Use the GTK interface"),
	OPT_BOOLEAN(0, "tui", &annotate.use_tui, "Use the TUI interface"),
	OPT_BOOLEAN(0, "stdio", &annotate.use_stdio, "Use the stdio interface"),
	OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
@@ -300,6 +304,8 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
		use_browser = 0;
	else if (annotate.use_tui)
		use_browser = 1;
	else if (annotate.use_gtk)
		use_browser = 2;

	setup_browser(true);

+185 −0
Original line number Diff line number Diff line
#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, "</span>");

	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, &notes->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, &notes->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;
}
+1 −1
Original line number Diff line number Diff line
@@ -8,7 +8,7 @@ pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER;

void setup_browser(bool fallback_to_pager)
{
	if (!isatty(1) || dump_trace)
	if (use_browser < 2 && (!isatty(1) || dump_trace))
		use_browser = 0;

	/* default to TUI */
Loading