All of lore.kernel.org
 help / color / mirror / Atom feed
From: Taeung Song <treeze.taeung@gmail.com>
To: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: linux-kernel@vger.kernel.org, Jiri Olsa <jolsa@kernel.org>,
	Namhyung Kim <namhyung@kernel.org>,
	Ingo Molnar <mingo@kernel.org>,
	Peter Zijlstra <peterz@infradead.org>,
	Wang Nan <wangnan0@huawei.com>,
	Masami Hiramatsu <mhiramat@kernel.org>,
	Taeung Song <treeze.taeung@gmail.com>,
	Jiri Olsa <jolsa@redhat.com>
Subject: [PATCH v3 7/7] perf annotate: Support the new source code view for TUI
Date: Fri, 10 Mar 2017 02:35:41 +0900	[thread overview]
Message-ID: <1489080941-3965-8-git-send-email-treeze.taeung@gmail.com> (raw)
In-Reply-To: <1489080941-3965-1-git-send-email-treeze.taeung@gmail.com>

To make source code view more readable,
add the new source code view for TUI
instead of confusing mixed source code & dissambly view.

This view can show source code per symbol(function).
and it can be toggled by a 's' key.
And support 'k' and 't' key for line numbers and total period.

For example, if target symbol is 'hex2u64' of util/util.c

Before:

       |    Disassembly of section .text:
       |
       |    000000000053ef9e <hex2u64>:
       |    hex2u64():
       |    /*
       |     * While we find nice hex chars, build a long_val.
       |     * Return number of chars processed.
       |     */
       |    int hex2u64(const char *ptr, u64 *long_val)
       |    {
       |      push   %rbp
  1.79 |      mov    %rsp,%rbp
       |      sub    $0x30,%rsp

After:

       |     * While we find nice hex chars, build a long_val.
       |     * Return number of chars processed.
       |     */
       |    int hex2u64(const char *ptr, u64 *long_val)
  1.79 |    {
       |        const char *p = ptr;
       |        *long_val = 0;
       |
 28.57 |        while (*p) {
 30.36 |                const int hex_val = hex(*p);
       |
 12.50 |                if (hex_val < 0)
       |                        break;
       |
 23.21 |                *long_val = (*long_val << 4) | hex_val;
       |                p++;
       |        }
       |
  1.79 |        return p - ptr;

Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Signed-off-by: Taeung Song <treeze.taeung@gmail.com>
---
 tools/perf/Documentation/perfconfig.example |   1 -
 tools/perf/ui/browsers/annotate.c           | 233 ++++++++++++++++++++--------
 tools/perf/util/annotate.c                  |  10 +-
 tools/perf/util/annotate.h                  |   7 +
 4 files changed, 180 insertions(+), 71 deletions(-)

diff --git a/tools/perf/Documentation/perfconfig.example b/tools/perf/Documentation/perfconfig.example
index 2b477c1..c9fc41b 100644
--- a/tools/perf/Documentation/perfconfig.example
+++ b/tools/perf/Documentation/perfconfig.example
@@ -23,7 +23,6 @@
 [annotate]
 
 	# Defaults
-	hide_src_code = false
 	use_offset = true
 	jump_arrows = true
 	show_nr_jumps = false
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 03b2012..ac01d75 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -27,8 +27,7 @@ struct browser_disasm_line {
 };
 
 static struct annotate_browser_opt {
-	bool hide_src_code,
-	     use_offset,
+	bool use_offset,
 	     jump_arrows,
 	     show_linenr,
 	     show_nr_jumps,
@@ -39,7 +38,7 @@ static struct annotate_browser_opt {
 };
 
 struct annotate_browser {
-	struct ui_browser b;
+	struct ui_browser b, cb;
 	struct rb_root	  entries;
 	struct rb_node	  *curr_hot;
 	struct disasm_line  *selection;
@@ -52,6 +51,7 @@ struct annotate_browser {
 	int		    nr_jumps;
 	bool		    searching_backwards;
 	bool		    have_cycles;
+	bool		    has_src_code;
 	u8		    addr_width;
 	u8		    jumps_width;
 	u8		    target_width;
@@ -68,12 +68,9 @@ static inline struct browser_disasm_line *disasm_line__browser(struct disasm_lin
 static bool disasm_line__filter(struct ui_browser *browser __maybe_unused,
 				void *entry)
 {
-	if (annotate_browser__opts.hide_src_code) {
-		struct disasm_line *dl = list_entry(entry, struct disasm_line, node);
-		return dl->offset == -1;
-	}
+	struct disasm_line *dl = list_entry(entry, struct disasm_line, node);
 
-	return false;
+	return dl->offset == -1;
 }
 
 static int annotate_browser__jumps_percent_color(struct annotate_browser *browser,
@@ -104,15 +101,61 @@ static int annotate_browser__pcnt_width(struct annotate_browser *ab)
 	return w;
 }
 
+static void annotate_code_browser__write(struct ui_browser *browser, void *entry, int row)
+{
+	struct annotate_browser *ab = container_of(browser, struct annotate_browser, cb);
+	struct code_line *cl = list_entry(entry, struct code_line, node);
+	bool current_entry = ui_browser__is_current_entry(browser, row);
+	int i, printed;
+	double percent, max_percent = 0.0;
+	char line[256];
+
+	for (i = 0; i < ab->nr_events; i++) {
+		if (cl->samples_sum[i].percent > max_percent)
+			max_percent = cl->samples_sum[i].percent;
+	}
+
+	for (i = 0; i < ab->nr_events; i++) {
+		if (max_percent == 0.0) {
+			ui_browser__set_percent_color(browser, 0, current_entry);
+			ui_browser__write_nstring(browser, " ", 7 * ab->nr_events);
+			break;
+		}
+
+		percent = cl->samples_sum[i].percent;
+		ui_browser__set_percent_color(browser, percent, current_entry);
+
+		if (annotate_browser__opts.show_total_period)
+			ui_browser__printf(browser, "%6" PRIu64 " ",
+					   cl->samples_sum[i].nr);
+		else
+			ui_browser__printf(browser, "%6.2f ", percent);
+
+		if (max_percent < percent)
+			max_percent = percent;
+	}
+
+	SLsmg_write_char(' ');
+
+	if (annotate_browser__opts.show_linenr)
+		printed = scnprintf(line, sizeof(line), "%-*d ",
+				    ab->addr_width + 2, cl->line_nr);
+	else
+		printed = scnprintf(line, sizeof(line), "%*s  ",
+				    ab->addr_width, " ");
+
+	ui_browser__write_nstring(browser, line, printed);
+	ui_browser__write_nstring(browser, cl->line, browser->width);
+}
+
 static void annotate_browser__write(struct ui_browser *browser, void *entry, int row)
 {
 	struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
 	struct disasm_line *dl = list_entry(entry, struct disasm_line, node);
 	struct browser_disasm_line *bdl = disasm_line__browser(dl);
 	bool current_entry = ui_browser__is_current_entry(browser, row);
-	bool change_color = (!annotate_browser__opts.hide_src_code &&
-			     (!current_entry || (browser->use_navkeypressed &&
-					         !browser->navkeypressed)));
+	bool change_color = !current_entry || (browser->use_navkeypressed &&
+					       !browser->navkeypressed);
 	int width = browser->width, printed;
 	int i, pcnt_width = annotate_browser__pcnt_width(ab);
 	double percent_max = 0.0;
@@ -271,19 +314,25 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)
 	bcursor = disasm_line__browser(cursor);
 	btarget = disasm_line__browser(target);
 
-	if (annotate_browser__opts.hide_src_code) {
-		from = bcursor->idx_asm;
-		to = btarget->idx_asm;
-	} else {
-		from = (u64)bcursor->idx;
-		to = (u64)btarget->idx;
-	}
+	from = bcursor->idx_asm;
+	to = btarget->idx_asm;
 
 	ui_browser__set_color(browser, HE_COLORSET_JUMP_ARROWS);
 	__ui_browser__line_arrow(browser, pcnt_width + 2 + ab->addr_width,
 				 from, to);
 }
 
+static unsigned int annotate_code_browser__refresh(struct ui_browser *browser)
+{
+	struct annotate_browser *ab = container_of(browser, struct annotate_browser, cb);
+	int ret = ui_browser__list_head_refresh(browser);
+	int pcnt_width = annotate_browser__pcnt_width(ab);
+
+	ui_browser__set_color(browser, HE_COLORSET_NORMAL);
+	__ui_browser__vline(browser, pcnt_width, 0, browser->height - 1);
+	return ret;
+}
+
 static unsigned int annotate_browser__refresh(struct ui_browser *browser)
 {
 	struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
@@ -364,12 +413,37 @@ static void annotate_browser__set_rb_top(struct annotate_browser *browser,
 	bpos = rb_entry(nd, struct browser_disasm_line, rb_node);
 	pos = ((struct disasm_line *)bpos) - 1;
 	idx = bpos->idx;
-	if (annotate_browser__opts.hide_src_code)
-		idx = bpos->idx_asm;
+	idx = bpos->idx_asm;
 	annotate_browser__set_top(browser, pos, idx);
 	browser->curr_hot = nd;
 }
 
+static void annotate_code_browser__calc_percent(struct annotate_browser *browser,
+						struct perf_evsel *evsel)
+{
+	int i;
+	struct map_symbol *ms = browser->b.priv;
+	struct symbol *sym = ms->sym;
+	struct annotation *notes = symbol__annotation(sym);
+	struct code_line *cl;
+	struct list_head *code_lines = browser->cb.entries;
+
+	pthread_mutex_lock(&notes->lock);
+
+	list_for_each_entry(cl, code_lines, node) {
+		for (i = 0; i < browser->nr_events; i++) {
+			cl->samples_sum[i].percent = 0.0;
+			cl->samples_sum[i].nr = 0;
+		}
+
+		for (i = 0; i < cl->nr_matched_dl; i++) {
+			code_line__sum_samples(cl, cl->matched_dl_arr[i], notes, evsel);
+		}
+	}
+
+	pthread_mutex_unlock(&notes->lock);
+}
+
 static void annotate_browser__calc_percent(struct annotate_browser *browser,
 					   struct perf_evsel *evsel)
 {
@@ -422,45 +496,6 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,
 	browser->curr_hot = rb_last(&browser->entries);
 }
 
-static bool annotate_browser__toggle_source(struct annotate_browser *browser)
-{
-	struct disasm_line *dl;
-	struct browser_disasm_line *bdl;
-	off_t offset = browser->b.index - browser->b.top_idx;
-
-	browser->b.seek(&browser->b, offset, SEEK_CUR);
-	dl = list_entry(browser->b.top, struct disasm_line, node);
-	bdl = disasm_line__browser(dl);
-
-	if (annotate_browser__opts.hide_src_code) {
-		if (bdl->idx_asm < offset)
-			offset = bdl->idx;
-
-		browser->b.nr_entries = browser->nr_entries;
-		annotate_browser__opts.hide_src_code = false;
-		browser->b.seek(&browser->b, -offset, SEEK_CUR);
-		browser->b.top_idx = bdl->idx - offset;
-		browser->b.index = bdl->idx;
-	} else {
-		if (bdl->idx_asm < 0) {
-			ui_helpline__puts("Only available for assembly lines.");
-			browser->b.seek(&browser->b, -offset, SEEK_CUR);
-			return false;
-		}
-
-		if (bdl->idx_asm < offset)
-			offset = bdl->idx_asm;
-
-		browser->b.nr_entries = browser->nr_asm_entries;
-		annotate_browser__opts.hide_src_code = true;
-		browser->b.seek(&browser->b, -offset, SEEK_CUR);
-		browser->b.top_idx = bdl->idx_asm - offset;
-		browser->b.index = bdl->idx_asm;
-	}
-
-	return true;
-}
-
 static void annotate_browser__init_asm_mode(struct annotate_browser *browser)
 {
 	ui_browser__reset_index(&browser->b);
@@ -696,6 +731,54 @@ static void annotate_browser__update_addr_width(struct annotate_browser *browser
 		browser->addr_width += browser->jumps_width + 1;
 }
 
+static int annotate_code_browser__run(struct annotate_browser *browser,
+				      struct perf_evsel *evsel, int delay_secs)
+{
+	int key;
+
+	if (ui_browser__show(&browser->cb, browser->cb.title, ui_helpline__current) < 0)
+		return -1;
+	annotate_code_browser__calc_percent(browser, evsel);
+
+	while (1) {
+
+		key = ui_browser__run(&browser->cb, delay_secs);
+		if (delay_secs != 0) {
+			annotate_code_browser__calc_percent(browser, evsel);
+		}
+
+		switch (key) {
+		case K_F1:
+		case 'h':
+			ui_browser__help_window(&browser->cb,
+		"UP/DOWN/PGUP\n"
+		"PGDN/SPACE    Navigate\n"
+		"q/ESC/CTRL+C  Return to dissembly view\n\n"
+		"s             Toggle source code view\n"
+		"t             Toggle total period view\n"
+		"k             Toggle line numbers\n");
+			continue;
+		case 't':
+			annotate_browser__opts.show_total_period =
+				!annotate_browser__opts.show_total_period;
+			continue;
+		case 'k':
+			annotate_browser__opts.show_linenr =
+				!annotate_browser__opts.show_linenr;
+			continue;
+		case 's':
+		case K_LEFT:
+		case K_ESC:
+		case 'q':
+		case CTRL('c'):
+			return 0;
+		default:
+			continue;
+		}
+	}
+	return 0;
+}
+
 static int annotate_browser__run(struct annotate_browser *browser,
 				 struct perf_evsel *evsel,
 				 struct hist_browser_timer *hbt)
@@ -775,7 +858,6 @@ static int annotate_browser__run(struct annotate_browser *browser,
 		"s             Toggle source code view\n"
 		"t             Toggle total period view\n"
 		"/             Search string\n"
-		"k             Toggle line numbers\n"
 		"r             Run available scripts\n"
 		"?             Search string backwards\n");
 			continue;
@@ -792,8 +874,11 @@ static int annotate_browser__run(struct annotate_browser *browser,
 			nd = browser->curr_hot;
 			break;
 		case 's':
-			if (annotate_browser__toggle_source(browser))
-				ui_helpline__puts(help);
+			if (browser->has_src_code) {
+				browser->cb.title = title;
+				annotate_code_browser__run(browser, evsel, delay_secs);
+			} else
+				ui_helpline__puts("No source code for the symbol");
 			continue;
 		case 'o':
 			annotate_browser__opts.use_offset = !annotate_browser__opts.use_offset;
@@ -1095,9 +1180,27 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
 	browser.b.entries = &notes->src->source,
 	browser.b.width += 18; /* Percentage */
 
-	if (annotate_browser__opts.hide_src_code)
-		annotate_browser__init_asm_mode(&browser);
+	if (symbol__get_source_code(sym, map, evsel) == 0) {
+		struct source_code *code = notes->src->code;
+		struct code_line *cl;
+
+		browser.has_src_code = true;
+		browser.cb.refresh = annotate_code_browser__refresh;
+		browser.cb.seek = ui_browser__list_head_seek;
+		browser.cb.write = annotate_code_browser__write;
+		browser.cb.use_navkeypressed = true;
+		browser.cb.entries = &code->lines;
+
+		list_for_each_entry(cl, &code->lines, node) {
+			size_t line_len = strlen(cl->line);
+
+			if (browser.cb.width < line_len)
+				browser.cb.width = line_len;
+			browser.cb.nr_entries++;
+		}
+	}
 
+	annotate_browser__init_asm_mode(&browser);
 	annotate_browser__update_addr_width(&browser);
 
 	ret = annotate_browser__run(&browser, evsel, hbt);
@@ -1105,6 +1208,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
 		list_del(&pos->node);
 		disasm_line__free(pos);
 	}
+	symbol__free_source_code(sym);
 
 out_free_offsets:
 	free(browser.offsets);
@@ -1121,7 +1225,6 @@ static struct annotate_config {
 	const char *name;
 	bool *value;
 } annotate__configs[] = {
-	ANNOTATE_CFG(hide_src_code),
 	ANNOTATE_CFG(jump_arrows),
 	ANNOTATE_CFG(show_linenr),
 	ANNOTATE_CFG(show_nr_jumps),
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 7d1c7cc..d8a3a50 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -1396,7 +1396,7 @@ static void code_lines__free(struct list_head *code_lines)
 	}
 }
 
-static int symbol__free_source_code(struct symbol *sym)
+int symbol__free_source_code(struct symbol *sym)
 {
 	struct annotation *notes = symbol__annotation(sym);
 	struct source_code *code = notes->src->code;
@@ -1410,8 +1410,8 @@ static int symbol__free_source_code(struct symbol *sym)
 	return 0;
 }
 
-static void code_line__sum_samples(struct code_line *cl, struct disasm_line *dl,
-				   struct annotation *notes, struct perf_evsel *evsel)
+void code_line__sum_samples(struct code_line *cl, struct disasm_line *dl,
+			    struct annotation *notes, struct perf_evsel *evsel)
 {
 	int i;
 	u64 nr_samples;
@@ -1569,8 +1569,8 @@ static int source_code__collect(struct source_code *code,
 	return ret;
 }
 
-static int symbol__get_source_code(struct symbol *sym, struct map *map,
-				   struct perf_evsel *evsel)
+int symbol__get_source_code(struct symbol *sym, struct map *map,
+			    struct perf_evsel *evsel)
 {
 	struct annotation *notes = symbol__annotation(sym);
 	struct source_code *code;
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index dd7ddae..e125eca 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -109,6 +109,9 @@ struct code_line {
 	struct disasm_line_samples *samples_sum;
 };
 
+void code_line__sum_samples(struct code_line *cl, struct disasm_line *dl,
+			    struct annotation *notes, struct perf_evsel *evsel);
+
 struct source_code {
 	char		 *path;
 	int		 nr_events;
@@ -180,6 +183,10 @@ int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 addr);
 int symbol__alloc_hist(struct symbol *sym);
 void symbol__annotate_zero_histograms(struct symbol *sym);
 
+int symbol__free_source_code(struct symbol *sym);
+int symbol__get_source_code(struct symbol *sym, struct map *map,
+			    struct perf_evsel *evsel);
+
 int symbol__disassemble(struct symbol *sym, struct map *map, const char *arch_name, size_t privsize);
 
 enum symbol_disassemble_errno {
-- 
2.7.4

      parent reply	other threads:[~2017-03-09 17:43 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-03-09 17:35 [PATCH v3 0/7] perf annotate: Fixes & Introduce --source-only and new source code view Taeung Song
2017-03-09 17:35 ` [PATCH v3 1/7] perf annotate: Use build-id dir when reading link name Taeung Song
2017-03-09 17:35 ` [PATCH v3 2/7] perf annotate: Avoid division by zero when calculating percent Taeung Song
2017-03-09 17:35 ` [PATCH v3 3/7] perf annotate: Fix missing setting nr samples on source_line Taeung Song
2017-03-09 17:35 ` [PATCH v3 4/7] perf annotate: More exactly grep -v in symbol__disassemble() Taeung Song
2017-03-09 17:35 ` [PATCH v3 5/7] perf annotate: Get correct line numbers matched with addr Taeung Song
2017-03-09 17:35 ` [PATCH v3 6/7] perf annotate: Introduce --source-only option Taeung Song
2017-03-09 17:35 ` Taeung Song [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1489080941-3965-8-git-send-email-treeze.taeung@gmail.com \
    --to=treeze.taeung@gmail.com \
    --cc=acme@kernel.org \
    --cc=jolsa@kernel.org \
    --cc=jolsa@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mhiramat@kernel.org \
    --cc=mingo@kernel.org \
    --cc=namhyung@kernel.org \
    --cc=peterz@infradead.org \
    --cc=wangnan0@huawei.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.