diff options
| author | Frederic Weisbecker <fweisbec@gmail.com> | 2009-06-13 00:11:22 +0200 | 
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2009-06-13 12:58:23 +0200 | 
| commit | 971738f3669092dd247eaf89658f2685180492a0 (patch) | |
| tree | 3b338afa8ecac80564769e0d6881e87b4587a2d3 | |
| parent | 301406b9c69e4914cf45ae9d5f929e7bcf0d93cd (diff) | |
perf annotate: Print a sorted summary of annotated overhead lines
It's can be very annoying to scroll down perf annotated output
until we find relevant overhead.
Using the -l option, you can now have a small summary sorted per
overhead in the beginning of the output.
Example:
./perf annotate -l -k ../../vmlinux -s __lock_acquire
Sorted summary for file ../../vmlinux
----------------------------------------------
   12.04 /home/fweisbec/linux/linux-2.6-tip/kernel/lockdep.c:1653
    4.61 /home/fweisbec/linux/linux-2.6-tip/kernel/lockdep.c:1740
    3.77 /home/fweisbec/linux/linux-2.6-tip/kernel/lockdep.c:1775
    3.56 /home/fweisbec/linux/linux-2.6-tip/kernel/lockdep.c:1653
    2.93 /home/fweisbec/linux/linux-2.6-tip/arch/x86/include/asm/irqflags.h:15
    2.83 /home/fweisbec/linux/linux-2.6-tip/kernel/lockdep.c:2545
    2.30 /home/fweisbec/linux/linux-2.6-tip/kernel/lockdep.c:2594
    2.20 /home/fweisbec/linux/linux-2.6-tip/kernel/lockdep.c:2388
    2.20 /home/fweisbec/linux/linux-2.6-tip/kernel/lockdep.c:730
    2.09 /home/fweisbec/linux/linux-2.6-tip/kernel/lockdep.c:730
    2.09 /home/fweisbec/linux/linux-2.6-tip/kernel/lockdep.c:138
    1.88 /home/fweisbec/linux/linux-2.6-tip/kernel/lockdep.c:2548
    1.47 /home/fweisbec/linux/linux-2.6-tip/arch/x86/include/asm/irqflags.h:15
    1.36 /home/fweisbec/linux/linux-2.6-tip/kernel/lockdep.c:2594
    1.36 /home/fweisbec/linux/linux-2.6-tip/kernel/lockdep.c:730
    1.26 /home/fweisbec/linux/linux-2.6-tip/kernel/lockdep.c:1654
    1.26 /home/fweisbec/linux/linux-2.6-tip/kernel/lockdep.c:1653
    1.15 /home/fweisbec/linux/linux-2.6-tip/kernel/lockdep.c:2592
    1.15 /home/fweisbec/linux/linux-2.6-tip/kernel/lockdep.c:1740
    1.15 /home/fweisbec/linux/linux-2.6-tip/kernel/lockdep.c:1740
[...]
Only overhead over 0.5% are summarized.
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1244844682-12928-2-git-send-email-fweisbec@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
| -rw-r--r-- | tools/perf/builtin-annotate.c | 111 | 
1 files changed, 90 insertions, 21 deletions
| diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 6a08da41f76..7a5b27867a9 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -25,6 +25,10 @@  #define SHOW_USER	2  #define SHOW_HV		4 +#define MIN_GREEN		0.5 +#define MIN_RED		5.0 + +  static char		const *input_name = "perf.data";  static char		*vmlinux = "vmlinux"; @@ -88,6 +92,7 @@ typedef union event_union {  struct sym_ext { +	struct rb_node	node;  	double		percent;  	char		*path;  }; @@ -1038,6 +1043,24 @@ process_event(event_t *event, unsigned long offset, unsigned long head)  	return 0;  } +static char *get_color(double percent) +{ +	char *color = PERF_COLOR_NORMAL; + +	/* +	 * We color high-overhead entries in red, mid-overhead +	 * entries in green - and keep the low overhead places +	 * normal: +	 */ +	if (percent >= MIN_RED) +		color = PERF_COLOR_RED; +	else { +		if (percent > MIN_GREEN) +			color = PERF_COLOR_GREEN; +	} +	return color; +} +  static int  parse_line(FILE *file, struct symbol *sym, __u64 start, __u64 len)  { @@ -1086,7 +1109,7 @@ parse_line(FILE *file, struct symbol *sym, __u64 start, __u64 len)  		const char *path = NULL;  		unsigned int hits = 0;  		double percent = 0.0; -		char *color = PERF_COLOR_NORMAL; +		char *color;  		struct sym_ext *sym_ext = sym->priv;  		offset = line_ip - start; @@ -1099,17 +1122,7 @@ parse_line(FILE *file, struct symbol *sym, __u64 start, __u64 len)  		} else if (sym->hist_sum)  			percent = 100.0 * hits / sym->hist_sum; -		/* -		 * We color high-overhead entries in red, mid-overhead -		 * entries in green - and keep the low overhead places -		 * normal: -		 */ -		if (percent >= 5.0) -			color = PERF_COLOR_RED; -		else { -			if (percent > 0.5) -				color = PERF_COLOR_GREEN; -		} +		color = get_color(percent);  		/*  		 * Also color the filename and line if needed, with @@ -1138,6 +1151,28 @@ parse_line(FILE *file, struct symbol *sym, __u64 start, __u64 len)  	return 0;  } +static struct rb_root root_sym_ext; + +static void insert_source_line(struct sym_ext *sym_ext) +{ +	struct sym_ext *iter; +	struct rb_node **p = &root_sym_ext.rb_node; +	struct rb_node *parent = NULL; + +	while (*p != NULL) { +		parent = *p; +		iter = rb_entry(parent, struct sym_ext, node); + +		if (sym_ext->percent > iter->percent) +			p = &(*p)->rb_left; +		else +			p = &(*p)->rb_right; +	} + +	rb_link_node(&sym_ext->node, parent, p); +	rb_insert_color(&sym_ext->node, &root_sym_ext); +} +  static void free_source_line(struct symbol *sym, int len)  {  	struct sym_ext *sym_ext = sym->priv; @@ -1151,6 +1186,7 @@ static void free_source_line(struct symbol *sym, int len)  	free(sym_ext);  	sym->priv = NULL; +	root_sym_ext = RB_ROOT;  }  /* Get the filename:line for the colored entries */ @@ -1193,12 +1229,42 @@ static void get_source_line(struct symbol *sym, __u64 start, int len)  			goto next;  		strcpy(sym_ext[i].path, path); +		insert_source_line(&sym_ext[i]);  	next:  		pclose(fp);  	}  } +static void print_summary(char *filename) +{ +	struct sym_ext *sym_ext; +	struct rb_node *node; + +	printf("\nSorted summary for file %s\n", filename); +	printf("----------------------------------------------\n\n"); + +	if (RB_EMPTY_ROOT(&root_sym_ext)) { +		printf(" Nothing higher than %1.1f%%\n", MIN_GREEN); +		return; +	} + +	node = rb_first(&root_sym_ext); +	while (node) { +		double percent; +		char *color; +		char *path; + +		sym_ext = rb_entry(node, struct sym_ext, node); +		percent = sym_ext->percent; +		color = get_color(percent); +		path = sym_ext->path; + +		color_fprintf(stdout, color, " %7.2f %s", percent, path); +		node = rb_next(node); +	} +} +  static void annotate_sym(struct dso *dso, struct symbol *sym)  {  	char *filename = dso->name; @@ -1211,13 +1277,6 @@ static void annotate_sym(struct dso *dso, struct symbol *sym)  	if (dso == kernel_dso)  		filename = vmlinux; -	printf("\n------------------------------------------------\n"); -	printf(" Percent |	Source code & Disassembly of %s\n", filename); -	printf("------------------------------------------------\n"); - -	if (verbose >= 2) -		printf("annotating [%p] %30s : [%p] %30s\n", dso, dso->name, sym, sym->name); -  	start = sym->obj_start;  	if (!start)  		start = sym->start; @@ -1225,8 +1284,17 @@ static void annotate_sym(struct dso *dso, struct symbol *sym)  	end = start + sym->end - sym->start + 1;  	len = sym->end - sym->start; -	if (print_line) +	if (print_line) {  		get_source_line(sym, start, len); +		print_summary(filename); +	} + +	printf("\n\n------------------------------------------------\n"); +	printf(" Percent |	Source code & Disassembly of %s\n", filename); +	printf("------------------------------------------------\n"); + +	if (verbose >= 2) +		printf("annotating [%p] %30s : [%p] %30s\n", dso, dso->name, sym, sym->name);  	sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s", (__u64)start, (__u64)end, filename); @@ -1243,7 +1311,8 @@ static void annotate_sym(struct dso *dso, struct symbol *sym)  	}  	pclose(file); -	free_source_line(sym, len); +	if (print_line) +		free_source_line(sym, len);  }  static void find_annotations(void) | 
