diff options
Diffstat (limited to 'tools/perf/ui/browsers/annotate.c')
| -rw-r--r-- | tools/perf/ui/browsers/annotate.c | 158 | 
1 files changed, 98 insertions, 60 deletions
| diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index 7dca1555c61..cc64d3f7fc3 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -8,15 +8,19 @@  #include "../../util/hist.h"  #include "../../util/sort.h"  #include "../../util/symbol.h" +#include "../../util/evsel.h"  #include <pthread.h> -#include <newt.h>  struct browser_disasm_line {  	struct rb_node	rb_node; -	double		percent;  	u32		idx;  	int		idx_asm;  	int		jump_sources; +	/* +	 * actual length of this array is saved on the nr_events field +	 * of the struct annotate_browser +	 */ +	double		percent[1];  };  static struct annotate_browser_opt { @@ -33,8 +37,9 @@ struct annotate_browser {  	struct ui_browser b;  	struct rb_root	  entries;  	struct rb_node	  *curr_hot; -	struct disasm_line	  *selection; +	struct disasm_line  *selection;  	struct disasm_line  **offsets; +	int		    nr_events;  	u64		    start;  	int		    nr_asm_entries;  	int		    nr_entries; @@ -94,14 +99,24 @@ 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; +	double percent_max = 0.0;  	char bf[256]; -	if (dl->offset != -1 && bdl->percent != 0.0) { -		ui_browser__set_percent_color(browser, bdl->percent, current_entry); -		slsmg_printf("%6.2f ", bdl->percent); +	for (i = 0; i < ab->nr_events; i++) { +		if (bdl->percent[i] > percent_max) +			percent_max = bdl->percent[i]; +	} + +	if (dl->offset != -1 && percent_max != 0.0) { +		for (i = 0; i < ab->nr_events; i++) { +			ui_browser__set_percent_color(browser, bdl->percent[i], +						      current_entry); +			slsmg_printf("%6.2f ", bdl->percent[i]); +		}  	} else {  		ui_browser__set_percent_color(browser, 0, current_entry); -		slsmg_write_nstring(" ", 7); +		slsmg_write_nstring(" ", pcnt_width);  	}  	SLsmg_write_char(' '); @@ -111,12 +126,12 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int  		width += 1;  	if (!*dl->line) -		slsmg_write_nstring(" ", width - 7); +		slsmg_write_nstring(" ", width - pcnt_width);  	else if (dl->offset == -1) {  		printed = scnprintf(bf, sizeof(bf), "%*s  ",  				    ab->addr_width, " ");  		slsmg_write_nstring(bf, printed); -		slsmg_write_nstring(dl->line, width - printed - 6); +		slsmg_write_nstring(dl->line, width - printed - pcnt_width + 1);  	} else {  		u64 addr = dl->offset;  		int color = -1; @@ -175,7 +190,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 - 10 - printed); +		slsmg_write_nstring(bf, width - pcnt_width - 3 - printed);  	}  	if (current_entry) @@ -200,6 +215,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;  	/* PLT symbols contain external offsets */  	if (strstr(sym->name, "@plt")) @@ -223,57 +239,44 @@ 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, 9 + ab->addr_width, from, to); +	__ui_browser__line_arrow(browser, pcnt_width + 2 + ab->addr_width, +				 from, to);  }  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;  	if (annotate_browser__opts.jump_arrows)  		annotate_browser__draw_current_jump(browser);  	ui_browser__set_color(browser, HE_COLORSET_NORMAL); -	__ui_browser__vline(browser, 7, 0, browser->height - 1); +	__ui_browser__vline(browser, pcnt_width, 0, browser->height - 1);  	return ret;  } -static double disasm_line__calc_percent(struct disasm_line *dl, struct symbol *sym, int evidx) +static int disasm__cmp(struct browser_disasm_line *a, +		       struct browser_disasm_line *b, int nr_pcnt)  { -	double percent = 0.0; - -	if (dl->offset != -1) { -		int len = sym->end - sym->start; -		unsigned int hits = 0; -		struct annotation *notes = symbol__annotation(sym); -		struct source_line *src_line = notes->src->lines; -		struct sym_hist *h = annotation__histogram(notes, evidx); -		s64 offset = dl->offset; -		struct disasm_line *next; +	int i; -		next = disasm__get_next_ip_line(¬es->src->source, dl); -		while (offset < (s64)len && -		       (next == NULL || offset < next->offset)) { -			if (src_line) { -				percent += src_line[offset].percent; -			} else -				hits += h->addr[offset]; - -			++offset; -		} -		/* - 		 * If the percentage wasn't already calculated in - 		 * symbol__get_source_line, do it now: - 		 */ -		if (src_line == NULL && h->sum) -			percent = 100.0 * hits / h->sum; +	for (i = 0; i < nr_pcnt; i++) { +		if (a->percent[i] == b->percent[i]) +			continue; +		return a->percent[i] < b->percent[i];  	} - -	return percent; +	return 0;  } -static void disasm_rb_tree__insert(struct rb_root *root, struct browser_disasm_line *bdl) +static void disasm_rb_tree__insert(struct rb_root *root, struct browser_disasm_line *bdl, +				   int nr_events)  {  	struct rb_node **p = &root->rb_node;  	struct rb_node *parent = NULL; @@ -282,7 +285,8 @@ static void disasm_rb_tree__insert(struct rb_root *root, struct browser_disasm_l  	while (*p != NULL) {  		parent = *p;  		l = rb_entry(parent, struct browser_disasm_line, rb_node); -		if (bdl->percent < l->percent) + +		if (disasm__cmp(bdl, l, nr_events))  			p = &(*p)->rb_left;  		else  			p = &(*p)->rb_right; @@ -331,12 +335,13 @@ static void annotate_browser__set_rb_top(struct annotate_browser *browser,  }  static void annotate_browser__calc_percent(struct annotate_browser *browser, -					   int evidx) +					   struct perf_evsel *evsel)  {  	struct map_symbol *ms = browser->b.priv;  	struct symbol *sym = ms->sym;  	struct annotation *notes = symbol__annotation(sym); -	struct disasm_line *pos; +	struct disasm_line *pos, *next; +	s64 len = symbol__size(sym);  	browser->entries = RB_ROOT; @@ -344,12 +349,34 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,  	list_for_each_entry(pos, ¬es->src->source, node) {  		struct browser_disasm_line *bpos = disasm_line__browser(pos); -		bpos->percent = disasm_line__calc_percent(pos, sym, evidx); -		if (bpos->percent < 0.01) { +		const char *path = NULL; +		double max_percent = 0.0; +		int i; + +		if (pos->offset == -1) { +			RB_CLEAR_NODE(&bpos->rb_node); +			continue; +		} + +		next = disasm__get_next_ip_line(¬es->src->source, pos); + +		for (i = 0; i < browser->nr_events; i++) { +			bpos->percent[i] = disasm__calc_percent(notes, +						evsel->idx + i, +						pos->offset, +						next ? next->offset : len, +					        &path); + +			if (max_percent < bpos->percent[i]) +				max_percent = bpos->percent[i]; +		} + +		if (max_percent < 0.01) {  			RB_CLEAR_NODE(&bpos->rb_node);  			continue;  		} -		disasm_rb_tree__insert(&browser->entries, bpos); +		disasm_rb_tree__insert(&browser->entries, bpos, +				       browser->nr_events);  	}  	pthread_mutex_unlock(¬es->lock); @@ -401,7 +428,8 @@ static void annotate_browser__init_asm_mode(struct annotate_browser *browser)  	browser->b.nr_entries = browser->nr_asm_entries;  } -static bool annotate_browser__callq(struct annotate_browser *browser, int evidx, +static bool annotate_browser__callq(struct annotate_browser *browser, +				    struct perf_evsel *evsel,  				    struct hist_browser_timer *hbt)  {  	struct map_symbol *ms = browser->b.priv; @@ -432,7 +460,7 @@ static bool annotate_browser__callq(struct annotate_browser *browser, int evidx,  	}  	pthread_mutex_unlock(¬es->lock); -	symbol__tui_annotate(target, ms->map, evidx, hbt); +	symbol__tui_annotate(target, ms->map, evsel, hbt);  	ui_browser__show_title(&browser->b, sym->name);  	return true;  } @@ -615,7 +643,8 @@ static void annotate_browser__update_addr_width(struct annotate_browser *browser  		browser->addr_width += browser->jumps_width + 1;  } -static int annotate_browser__run(struct annotate_browser *browser, int evidx, +static int annotate_browser__run(struct annotate_browser *browser, +				 struct perf_evsel *evsel,  				 struct hist_browser_timer *hbt)  {  	struct rb_node *nd = NULL; @@ -628,7 +657,7 @@ static int annotate_browser__run(struct annotate_browser *browser, int evidx,  	if (ui_browser__show(&browser->b, sym->name, help) < 0)  		return -1; -	annotate_browser__calc_percent(browser, evidx); +	annotate_browser__calc_percent(browser, evsel);  	if (browser->curr_hot) {  		annotate_browser__set_rb_top(browser, browser->curr_hot); @@ -641,7 +670,7 @@ static int annotate_browser__run(struct annotate_browser *browser, int evidx,  		key = ui_browser__run(&browser->b, delay_secs);  		if (delay_secs != 0) { -			annotate_browser__calc_percent(browser, evidx); +			annotate_browser__calc_percent(browser, evsel);  			/*  			 * Current line focus got out of the list of most active  			 * lines, NULL it so that if TAB|UNTAB is pressed, we @@ -657,7 +686,7 @@ static int annotate_browser__run(struct annotate_browser *browser, int evidx,  				hbt->timer(hbt->arg);  			if (delay_secs != 0) -				symbol__annotate_decay_histogram(sym, evidx); +				symbol__annotate_decay_histogram(sym, evsel->idx);  			continue;  		case K_TAB:  			if (nd != NULL) { @@ -754,7 +783,7 @@ show_help:  					goto show_sup_ins;  				goto out;  			} else if (!(annotate_browser__jump(browser) || -				     annotate_browser__callq(browser, evidx, hbt))) { +				     annotate_browser__callq(browser, evsel, hbt))) {  show_sup_ins:  				ui_helpline__puts("Actions are only available for 'callq', 'retq' & jump instructions.");  			} @@ -776,10 +805,10 @@ out:  	return key;  } -int hist_entry__tui_annotate(struct hist_entry *he, int evidx, +int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,  			     struct hist_browser_timer *hbt)  { -	return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx, hbt); +	return symbol__tui_annotate(he->ms.sym, he->ms.map, evsel, hbt);  }  static void annotate_browser__mark_jump_targets(struct annotate_browser *browser, @@ -826,7 +855,8 @@ static inline int width_jumps(int n)  	return 1;  } -int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, +int symbol__tui_annotate(struct symbol *sym, struct map *map, +			 struct perf_evsel *evsel,  			 struct hist_browser_timer *hbt)  {  	struct disasm_line *pos, *n; @@ -847,6 +877,8 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,  		},  	};  	int ret = -1; +	int nr_pcnt = 1; +	size_t sizeof_bdl = sizeof(struct browser_disasm_line);  	if (sym == NULL)  		return -1; @@ -862,7 +894,12 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,  		return -1;  	} -	if (symbol__annotate(sym, map, sizeof(struct browser_disasm_line)) < 0) { +	if (perf_evsel__is_group_event(evsel)) { +		nr_pcnt = evsel->nr_members; +		sizeof_bdl += sizeof(double) * (nr_pcnt - 1); +	} + +	if (symbol__annotate(sym, map, sizeof_bdl) < 0) {  		ui__error("%s", ui_helpline__last_msg);  		goto out_free_offsets;  	} @@ -900,6 +937,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,  	browser.addr_width = browser.target_width = browser.min_addr_width = hex_width(size);  	browser.max_addr_width = hex_width(sym->end);  	browser.jumps_width = width_jumps(browser.max_jump_sources); +	browser.nr_events = nr_pcnt;  	browser.b.nr_entries = browser.nr_entries;  	browser.b.entries = ¬es->src->source,  	browser.b.width += 18; /* Percentage */ @@ -909,7 +947,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,  	annotate_browser__update_addr_width(&browser); -	ret = annotate_browser__run(&browser, evidx, hbt); +	ret = annotate_browser__run(&browser, evsel, hbt);  	list_for_each_entry_safe(pos, n, ¬es->src->source, node) {  		list_del(&pos->node);  		disasm_line__free(pos); |