aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2009-06-12 18:11:22 -0400
committerIngo Molnar <mingo@elte.hu>2009-06-13 06:58:23 -0400
commit971738f3669092dd247eaf89658f2685180492a0 (patch)
tree3b338afa8ecac80564769e0d6881e87b4587a2d3
parent301406b9c69e4914cf45ae9d5f929e7bcf0d93cd (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.c111
1 files changed, 90 insertions, 21 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 6a08da41f76b..7a5b27867a96 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -25,6 +25,10 @@
25#define SHOW_USER 2 25#define SHOW_USER 2
26#define SHOW_HV 4 26#define SHOW_HV 4
27 27
28#define MIN_GREEN 0.5
29#define MIN_RED 5.0
30
31
28static char const *input_name = "perf.data"; 32static char const *input_name = "perf.data";
29static char *vmlinux = "vmlinux"; 33static char *vmlinux = "vmlinux";
30 34
@@ -88,6 +92,7 @@ typedef union event_union {
88 92
89 93
90struct sym_ext { 94struct sym_ext {
95 struct rb_node node;
91 double percent; 96 double percent;
92 char *path; 97 char *path;
93}; 98};
@@ -1038,6 +1043,24 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
1038 return 0; 1043 return 0;
1039} 1044}
1040 1045
1046static char *get_color(double percent)
1047{
1048 char *color = PERF_COLOR_NORMAL;
1049
1050 /*
1051 * We color high-overhead entries in red, mid-overhead
1052 * entries in green - and keep the low overhead places
1053 * normal:
1054 */
1055 if (percent >= MIN_RED)
1056 color = PERF_COLOR_RED;
1057 else {
1058 if (percent > MIN_GREEN)
1059 color = PERF_COLOR_GREEN;
1060 }
1061 return color;
1062}
1063
1041static int 1064static int
1042parse_line(FILE *file, struct symbol *sym, __u64 start, __u64 len) 1065parse_line(FILE *file, struct symbol *sym, __u64 start, __u64 len)
1043{ 1066{
@@ -1086,7 +1109,7 @@ parse_line(FILE *file, struct symbol *sym, __u64 start, __u64 len)
1086 const char *path = NULL; 1109 const char *path = NULL;
1087 unsigned int hits = 0; 1110 unsigned int hits = 0;
1088 double percent = 0.0; 1111 double percent = 0.0;
1089 char *color = PERF_COLOR_NORMAL; 1112 char *color;
1090 struct sym_ext *sym_ext = sym->priv; 1113 struct sym_ext *sym_ext = sym->priv;
1091 1114
1092 offset = line_ip - start; 1115 offset = line_ip - start;
@@ -1099,17 +1122,7 @@ parse_line(FILE *file, struct symbol *sym, __u64 start, __u64 len)
1099 } else if (sym->hist_sum) 1122 } else if (sym->hist_sum)
1100 percent = 100.0 * hits / sym->hist_sum; 1123 percent = 100.0 * hits / sym->hist_sum;
1101 1124
1102 /* 1125 color = get_color(percent);
1103 * We color high-overhead entries in red, mid-overhead
1104 * entries in green - and keep the low overhead places
1105 * normal:
1106 */
1107 if (percent >= 5.0)
1108 color = PERF_COLOR_RED;
1109 else {
1110 if (percent > 0.5)
1111 color = PERF_COLOR_GREEN;
1112 }
1113 1126
1114 /* 1127 /*
1115 * Also color the filename and line if needed, with 1128 * Also color the filename and line if needed, with
@@ -1138,6 +1151,28 @@ parse_line(FILE *file, struct symbol *sym, __u64 start, __u64 len)
1138 return 0; 1151 return 0;
1139} 1152}
1140 1153
1154static struct rb_root root_sym_ext;
1155
1156static void insert_source_line(struct sym_ext *sym_ext)
1157{
1158 struct sym_ext *iter;
1159 struct rb_node **p = &root_sym_ext.rb_node;
1160 struct rb_node *parent = NULL;
1161
1162 while (*p != NULL) {
1163 parent = *p;
1164 iter = rb_entry(parent, struct sym_ext, node);
1165
1166 if (sym_ext->percent > iter->percent)
1167 p = &(*p)->rb_left;
1168 else
1169 p = &(*p)->rb_right;
1170 }
1171
1172 rb_link_node(&sym_ext->node, parent, p);
1173 rb_insert_color(&sym_ext->node, &root_sym_ext);
1174}
1175
1141static void free_source_line(struct symbol *sym, int len) 1176static void free_source_line(struct symbol *sym, int len)
1142{ 1177{
1143 struct sym_ext *sym_ext = sym->priv; 1178 struct sym_ext *sym_ext = sym->priv;
@@ -1151,6 +1186,7 @@ static void free_source_line(struct symbol *sym, int len)
1151 free(sym_ext); 1186 free(sym_ext);
1152 1187
1153 sym->priv = NULL; 1188 sym->priv = NULL;
1189 root_sym_ext = RB_ROOT;
1154} 1190}
1155 1191
1156/* Get the filename:line for the colored entries */ 1192/* Get the filename:line for the colored entries */
@@ -1193,12 +1229,42 @@ static void get_source_line(struct symbol *sym, __u64 start, int len)
1193 goto next; 1229 goto next;
1194 1230
1195 strcpy(sym_ext[i].path, path); 1231 strcpy(sym_ext[i].path, path);
1232 insert_source_line(&sym_ext[i]);
1196 1233
1197 next: 1234 next:
1198 pclose(fp); 1235 pclose(fp);
1199 } 1236 }
1200} 1237}
1201 1238
1239static void print_summary(char *filename)
1240{
1241 struct sym_ext *sym_ext;
1242 struct rb_node *node;
1243
1244 printf("\nSorted summary for file %s\n", filename);
1245 printf("----------------------------------------------\n\n");
1246
1247 if (RB_EMPTY_ROOT(&root_sym_ext)) {
1248 printf(" Nothing higher than %1.1f%%\n", MIN_GREEN);
1249 return;
1250 }
1251
1252 node = rb_first(&root_sym_ext);
1253 while (node) {
1254 double percent;
1255 char *color;
1256 char *path;
1257
1258 sym_ext = rb_entry(node, struct sym_ext, node);
1259 percent = sym_ext->percent;
1260 color = get_color(percent);
1261 path = sym_ext->path;
1262
1263 color_fprintf(stdout, color, " %7.2f %s", percent, path);
1264 node = rb_next(node);
1265 }
1266}
1267
1202static void annotate_sym(struct dso *dso, struct symbol *sym) 1268static void annotate_sym(struct dso *dso, struct symbol *sym)
1203{ 1269{
1204 char *filename = dso->name; 1270 char *filename = dso->name;
@@ -1211,13 +1277,6 @@ static void annotate_sym(struct dso *dso, struct symbol *sym)
1211 if (dso == kernel_dso) 1277 if (dso == kernel_dso)
1212 filename = vmlinux; 1278 filename = vmlinux;
1213 1279
1214 printf("\n------------------------------------------------\n");
1215 printf(" Percent | Source code & Disassembly of %s\n", filename);
1216 printf("------------------------------------------------\n");
1217
1218 if (verbose >= 2)
1219 printf("annotating [%p] %30s : [%p] %30s\n", dso, dso->name, sym, sym->name);
1220
1221 start = sym->obj_start; 1280 start = sym->obj_start;
1222 if (!start) 1281 if (!start)
1223 start = sym->start; 1282 start = sym->start;
@@ -1225,8 +1284,17 @@ static void annotate_sym(struct dso *dso, struct symbol *sym)
1225 end = start + sym->end - sym->start + 1; 1284 end = start + sym->end - sym->start + 1;
1226 len = sym->end - sym->start; 1285 len = sym->end - sym->start;
1227 1286
1228 if (print_line) 1287 if (print_line) {
1229 get_source_line(sym, start, len); 1288 get_source_line(sym, start, len);
1289 print_summary(filename);
1290 }
1291
1292 printf("\n\n------------------------------------------------\n");
1293 printf(" Percent | Source code & Disassembly of %s\n", filename);
1294 printf("------------------------------------------------\n");
1295
1296 if (verbose >= 2)
1297 printf("annotating [%p] %30s : [%p] %30s\n", dso, dso->name, sym, sym->name);
1230 1298
1231 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s", (__u64)start, (__u64)end, filename); 1299 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s", (__u64)start, (__u64)end, filename);
1232 1300
@@ -1243,7 +1311,8 @@ static void annotate_sym(struct dso *dso, struct symbol *sym)
1243 } 1311 }
1244 1312
1245 pclose(file); 1313 pclose(file);
1246 free_source_line(sym, len); 1314 if (print_line)
1315 free_source_line(sym, len);
1247} 1316}
1248 1317
1249static void find_annotations(void) 1318static void find_annotations(void)