diff options
Diffstat (limited to 'tools/perf/ui/browsers/annotate.c')
| -rw-r--r-- | tools/perf/ui/browsers/annotate.c | 149 | 
1 files changed, 122 insertions, 27 deletions
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index 5995a8bd7c69..29739b347599 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -1,7 +1,6 @@  #include "../../util/util.h"  #include "../browser.h"  #include "../helpline.h" -#include "../libslang.h"  #include "../ui.h"  #include "../util.h"  #include "../../util/annotate.h" @@ -16,6 +15,9 @@ struct disasm_line_samples {  	u64		nr;  }; +#define IPC_WIDTH 6 +#define CYCLES_WIDTH 6 +  struct browser_disasm_line {  	struct rb_node			rb_node;  	u32				idx; @@ -53,6 +55,7 @@ struct annotate_browser {  	int		    max_jump_sources;  	int		    nr_jumps;  	bool		    searching_backwards; +	bool		    have_cycles;  	u8		    addr_width;  	u8		    jumps_width;  	u8		    target_width; @@ -96,6 +99,15 @@ static int annotate_browser__set_jumps_percent_color(struct annotate_browser *br  	 return ui_browser__set_color(&browser->b, color);  } +static int annotate_browser__pcnt_width(struct annotate_browser *ab) +{ +	int w = 7 * ab->nr_events; + +	if (ab->have_cycles) +		w += IPC_WIDTH + CYCLES_WIDTH; +	return w; +} +  static void annotate_browser__write(struct ui_browser *browser, void *entry, int row)  {  	struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); @@ -106,7 +118,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int  			     (!current_entry || (browser->use_navkeypressed &&  					         !browser->navkeypressed)));  	int width = browser->width, printed; -	int i, pcnt_width = 7 * ab->nr_events; +	int i, pcnt_width = annotate_browser__pcnt_width(ab);  	double percent_max = 0.0;  	char bf[256]; @@ -116,19 +128,36 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int  	}  	if (dl->offset != -1 && percent_max != 0.0) { -		for (i = 0; i < ab->nr_events; i++) { -			ui_browser__set_percent_color(browser, -						      bdl->samples[i].percent, -						      current_entry); -			if (annotate_browser__opts.show_total_period) -				slsmg_printf("%6" PRIu64 " ", -					     bdl->samples[i].nr); -			else -				slsmg_printf("%6.2f ", bdl->samples[i].percent); +		if (percent_max != 0.0) { +			for (i = 0; i < ab->nr_events; i++) { +				ui_browser__set_percent_color(browser, +							bdl->samples[i].percent, +							current_entry); +				if (annotate_browser__opts.show_total_period) { +					ui_browser__printf(browser, "%6" PRIu64 " ", +							   bdl->samples[i].nr); +				} else { +					ui_browser__printf(browser, "%6.2f ", +							   bdl->samples[i].percent); +				} +			} +		} else { +			ui_browser__write_nstring(browser, " ", 7 * ab->nr_events);  		}  	} else {  		ui_browser__set_percent_color(browser, 0, current_entry); -		slsmg_write_nstring(" ", pcnt_width); +		ui_browser__write_nstring(browser, " ", 7 * ab->nr_events); +	} +	if (ab->have_cycles) { +		if (dl->ipc) +			ui_browser__printf(browser, "%*.2f ", IPC_WIDTH - 1, dl->ipc); +		else +			ui_browser__write_nstring(browser, " ", IPC_WIDTH); +		if (dl->cycles) +			ui_browser__printf(browser, "%*" PRIu64 " ", +					   CYCLES_WIDTH - 1, dl->cycles); +		else +			ui_browser__write_nstring(browser, " ", CYCLES_WIDTH);  	}  	SLsmg_write_char(' '); @@ -138,7 +167,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int  		width += 1;  	if (!*dl->line) -		slsmg_write_nstring(" ", width - pcnt_width); +		ui_browser__write_nstring(browser, " ", width - pcnt_width);  	else if (dl->offset == -1) {  		if (dl->line_nr && annotate_browser__opts.show_linenr)  			printed = scnprintf(bf, sizeof(bf), "%-*d ", @@ -146,8 +175,8 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int  		else  			printed = scnprintf(bf, sizeof(bf), "%*s  ",  				    ab->addr_width, " "); -		slsmg_write_nstring(bf, printed); -		slsmg_write_nstring(dl->line, width - printed - pcnt_width + 1); +		ui_browser__write_nstring(browser, bf, printed); +		ui_browser__write_nstring(browser, dl->line, width - printed - pcnt_width + 1);  	} else {  		u64 addr = dl->offset;  		int color = -1; @@ -166,7 +195,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int  							    bdl->jump_sources);  					prev = annotate_browser__set_jumps_percent_color(ab, bdl->jump_sources,  											 current_entry); -					slsmg_write_nstring(bf, printed); +					ui_browser__write_nstring(browser, bf, printed);  					ui_browser__set_color(browser, prev);  				} @@ -180,7 +209,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int  		if (change_color)  			color = ui_browser__set_color(browser, HE_COLORSET_ADDR); -		slsmg_write_nstring(bf, printed); +		ui_browser__write_nstring(browser, bf, printed);  		if (change_color)  			ui_browser__set_color(browser, color);  		if (dl->ins && dl->ins->ops->scnprintf) { @@ -194,11 +223,11 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int  				ui_browser__write_graph(browser, SLSMG_RARROW_CHAR);  				SLsmg_write_char(' ');  			} else { -				slsmg_write_nstring(" ", 2); +				ui_browser__write_nstring(browser, " ", 2);  			}  		} else {  			if (strcmp(dl->name, "retq")) { -				slsmg_write_nstring(" ", 2); +				ui_browser__write_nstring(browser, " ", 2);  			} else {  				ui_browser__write_graph(browser, SLSMG_LARROW_CHAR);  				SLsmg_write_char(' '); @@ -206,7 +235,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int  		}  		disasm_line__scnprintf(dl, bf, sizeof(bf), !annotate_browser__opts.use_offset); -		slsmg_write_nstring(bf, width - pcnt_width - 3 - printed); +		ui_browser__write_nstring(browser, bf, width - pcnt_width - 3 - printed);  	}  	if (current_entry) @@ -231,7 +260,7 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)  	unsigned int from, to;  	struct map_symbol *ms = ab->b.priv;  	struct symbol *sym = ms->sym; -	u8 pcnt_width = 7; +	u8 pcnt_width = annotate_browser__pcnt_width(ab);  	/* PLT symbols contain external offsets */  	if (strstr(sym->name, "@plt")) @@ -255,8 +284,6 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)  		to = (u64)btarget->idx;  	} -	pcnt_width *= ab->nr_events; -  	ui_browser__set_color(browser, HE_COLORSET_CODE);  	__ui_browser__line_arrow(browser, pcnt_width + 2 + ab->addr_width,  				 from, to); @@ -266,9 +293,7 @@ static unsigned int annotate_browser__refresh(struct ui_browser *browser)  {  	struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);  	int ret = ui_browser__list_head_refresh(browser); -	int pcnt_width; - -	pcnt_width = 7 * ab->nr_events; +	int pcnt_width = annotate_browser__pcnt_width(ab);  	if (annotate_browser__opts.jump_arrows)  		annotate_browser__draw_current_jump(browser); @@ -390,7 +415,7 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,  				max_percent = bpos->samples[i].percent;  		} -		if (max_percent < 0.01) { +		if (max_percent < 0.01 && pos->ipc == 0) {  			RB_CLEAR_NODE(&bpos->rb_node);  			continue;  		} @@ -869,6 +894,75 @@ int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,  	return map_symbol__tui_annotate(&he->ms, evsel, hbt);  } + +static unsigned count_insn(struct annotate_browser *browser, u64 start, u64 end) +{ +	unsigned n_insn = 0; +	u64 offset; + +	for (offset = start; offset <= end; offset++) { +		if (browser->offsets[offset]) +			n_insn++; +	} +	return n_insn; +} + +static void count_and_fill(struct annotate_browser *browser, u64 start, u64 end, +			   struct cyc_hist *ch) +{ +	unsigned n_insn; +	u64 offset; + +	n_insn = count_insn(browser, start, end); +	if (n_insn && ch->num && ch->cycles) { +		float ipc = n_insn / ((double)ch->cycles / (double)ch->num); + +		/* Hide data when there are too many overlaps. */ +		if (ch->reset >= 0x7fff || ch->reset >= ch->num / 2) +			return; + +		for (offset = start; offset <= end; offset++) { +			struct disasm_line *dl = browser->offsets[offset]; + +			if (dl) +				dl->ipc = ipc; +		} +	} +} + +/* + * This should probably be in util/annotate.c to share with the tty + * annotate, but right now we need the per byte offsets arrays, + * which are only here. + */ +static void annotate__compute_ipc(struct annotate_browser *browser, size_t size, +			   struct symbol *sym) +{ +	u64 offset; +	struct annotation *notes = symbol__annotation(sym); + +	if (!notes->src || !notes->src->cycles_hist) +		return; + +	pthread_mutex_lock(¬es->lock); +	for (offset = 0; offset < size; ++offset) { +		struct cyc_hist *ch; + +		ch = ¬es->src->cycles_hist[offset]; +		if (ch && ch->cycles) { +			struct disasm_line *dl; + +			if (ch->have_start) +				count_and_fill(browser, ch->start, offset, ch); +			dl = browser->offsets[offset]; +			if (dl && ch->num_aggr) +				dl->cycles = ch->cycles_aggr / ch->num_aggr; +			browser->have_cycles = true; +		} +	} +	pthread_mutex_unlock(¬es->lock); +} +  static void annotate_browser__mark_jump_targets(struct annotate_browser *browser,  						size_t size)  { @@ -991,6 +1085,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,  	}  	annotate_browser__mark_jump_targets(&browser, size); +	annotate__compute_ipc(&browser, size, sym);  	browser.addr_width = browser.target_width = browser.min_addr_width = hex_width(size);  	browser.max_addr_width = hex_width(sym->end);  | 
