aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-annotate.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2009-10-20 12:25:40 -0400
committerIngo Molnar <mingo@elte.hu>2009-10-20 15:12:58 -0400
commite42049926ebdcae24fdfdc8f0e3ff8f05f24a60b (patch)
treebe0a07b62070aef5edcd64d84e12e04950220590 /tools/perf/builtin-annotate.c
parented52ce2e3c33dc7626a40fa2da766d1a6460e543 (diff)
perf annotate: Use the sym_priv_size area for the histogram
We have this sym_priv_size mechanism for attaching private areas to struct symbol entries but annotate wasn't using it, adding private areas to struct symbol in addition to a ->priv pointer. Scrap all that and use the sym_priv_size mechanism. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Mike Galbraith <efault@gmx.de> LKML-Reference: <1256055940-19511-1-git-send-email-acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/builtin-annotate.c')
-rw-r--r--tools/perf/builtin-annotate.c109
1 files changed, 79 insertions, 30 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 06f10278b28e..245692530de1 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -37,12 +37,44 @@ static int print_line;
37static unsigned long page_size; 37static unsigned long page_size;
38static unsigned long mmap_window = 32; 38static unsigned long mmap_window = 32;
39 39
40struct sym_hist {
41 u64 sum;
42 u64 ip[0];
43};
44
40struct sym_ext { 45struct sym_ext {
41 struct rb_node node; 46 struct rb_node node;
42 double percent; 47 double percent;
43 char *path; 48 char *path;
44}; 49};
45 50
51struct sym_priv {
52 struct sym_hist *hist;
53 struct sym_ext *ext;
54};
55
56static const char *sym_hist_filter;
57
58static int symbol_filter(struct map *map, struct symbol *sym)
59{
60 if (strcmp(sym->name, sym_hist_filter) == 0) {
61 struct sym_priv *priv = dso__sym_priv(map->dso, sym);
62 const int size = (sizeof(*priv->hist) +
63 (sym->end - sym->start) * sizeof(u64));
64
65 priv->hist = malloc(size);
66 if (priv->hist)
67 memset(priv->hist, 0, size);
68 return 0;
69 }
70 /*
71 * FIXME: We should really filter it out, as we don't want to go thru symbols
72 * we're not interested, and if a DSO ends up with no symbols, delete it too,
73 * but right now the kernel loading routines in symbol.c bail out if no symbols
74 * are found, fix it later.
75 */
76 return 0;
77}
46 78
47/* 79/*
48 * collect histogram counts 80 * collect histogram counts
@@ -51,10 +83,16 @@ static void hist_hit(struct hist_entry *he, u64 ip)
51{ 83{
52 unsigned int sym_size, offset; 84 unsigned int sym_size, offset;
53 struct symbol *sym = he->sym; 85 struct symbol *sym = he->sym;
86 struct sym_priv *priv;
87 struct sym_hist *h;
54 88
55 he->count++; 89 he->count++;
56 90
57 if (!sym || !sym->hist) 91 if (!sym || !he->map)
92 return;
93
94 priv = dso__sym_priv(he->map->dso, sym);
95 if (!priv->hist)
58 return; 96 return;
59 97
60 sym_size = sym->end - sym->start; 98 sym_size = sym->end - sym->start;
@@ -67,15 +105,16 @@ static void hist_hit(struct hist_entry *he, u64 ip)
67 if (offset >= sym_size) 105 if (offset >= sym_size)
68 return; 106 return;
69 107
70 sym->hist_sum++; 108 h = priv->hist;
71 sym->hist[offset]++; 109 h->sum++;
110 h->ip[offset]++;
72 111
73 if (verbose >= 3) 112 if (verbose >= 3)
74 printf("%p %s: count++ [ip: %p, %08Lx] => %Ld\n", 113 printf("%p %s: count++ [ip: %p, %08Lx] => %Ld\n",
75 (void *)(unsigned long)he->sym->start, 114 (void *)(unsigned long)he->sym->start,
76 he->sym->name, 115 he->sym->name,
77 (void *)(unsigned long)ip, ip - he->sym->start, 116 (void *)(unsigned long)ip, ip - he->sym->start,
78 sym->hist[offset]); 117 h->ip[offset]);
79} 118}
80 119
81static int hist_entry__add(struct thread *thread, struct map *map, 120static int hist_entry__add(struct thread *thread, struct map *map,
@@ -162,7 +201,9 @@ got_map:
162static int 201static int
163process_mmap_event(event_t *event, unsigned long offset, unsigned long head) 202process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
164{ 203{
165 struct map *map = map__new(&event->mmap, NULL, 0); 204 struct map *map = map__new(&event->mmap, NULL, 0,
205 sizeof(struct sym_priv), symbol_filter,
206 verbose);
166 struct thread *thread = threads__findnew(event->mmap.pid); 207 struct thread *thread = threads__findnew(event->mmap.pid);
167 208
168 dump_printf("%p [%p]: PERF_RECORD_MMAP %d: [%p(%p) @ %p]: %s\n", 209 dump_printf("%p [%p]: PERF_RECORD_MMAP %d: [%p(%p) @ %p]: %s\n",
@@ -314,17 +355,19 @@ static int parse_line(FILE *file, struct hist_entry *he, u64 len)
314 unsigned int hits = 0; 355 unsigned int hits = 0;
315 double percent = 0.0; 356 double percent = 0.0;
316 const char *color; 357 const char *color;
317 struct sym_ext *sym_ext = sym->priv; 358 struct sym_priv *priv = dso__sym_priv(he->map->dso, sym);
359 struct sym_ext *sym_ext = priv->ext;
360 struct sym_hist *h = priv->hist;
318 361
319 offset = line_ip - start; 362 offset = line_ip - start;
320 if (offset < len) 363 if (offset < len)
321 hits = sym->hist[offset]; 364 hits = h->ip[offset];
322 365
323 if (offset < len && sym_ext) { 366 if (offset < len && sym_ext) {
324 path = sym_ext[offset].path; 367 path = sym_ext[offset].path;
325 percent = sym_ext[offset].percent; 368 percent = sym_ext[offset].percent;
326 } else if (sym->hist_sum) 369 } else if (h->sum)
327 percent = 100.0 * hits / sym->hist_sum; 370 percent = 100.0 * hits / h->sum;
328 371
329 color = get_percent_color(percent); 372 color = get_percent_color(percent);
330 373
@@ -377,9 +420,10 @@ static void insert_source_line(struct sym_ext *sym_ext)
377 rb_insert_color(&sym_ext->node, &root_sym_ext); 420 rb_insert_color(&sym_ext->node, &root_sym_ext);
378} 421}
379 422
380static void free_source_line(struct symbol *sym, int len) 423static void free_source_line(struct hist_entry *he, int len)
381{ 424{
382 struct sym_ext *sym_ext = sym->priv; 425 struct sym_priv *priv = dso__sym_priv(he->map->dso, he->sym);
426 struct sym_ext *sym_ext = priv->ext;
383 int i; 427 int i;
384 428
385 if (!sym_ext) 429 if (!sym_ext)
@@ -389,7 +433,7 @@ static void free_source_line(struct symbol *sym, int len)
389 free(sym_ext[i].path); 433 free(sym_ext[i].path);
390 free(sym_ext); 434 free(sym_ext);
391 435
392 sym->priv = NULL; 436 priv->ext = NULL;
393 root_sym_ext = RB_ROOT; 437 root_sym_ext = RB_ROOT;
394} 438}
395 439
@@ -402,15 +446,16 @@ get_source_line(struct hist_entry *he, int len, const char *filename)
402 int i; 446 int i;
403 char cmd[PATH_MAX * 2]; 447 char cmd[PATH_MAX * 2];
404 struct sym_ext *sym_ext; 448 struct sym_ext *sym_ext;
449 struct sym_priv *priv = dso__sym_priv(he->map->dso, sym);
450 struct sym_hist *h = priv->hist;
405 451
406 if (!sym->hist_sum) 452 if (!h->sum)
407 return; 453 return;
408 454
409 sym->priv = calloc(len, sizeof(struct sym_ext)); 455 sym_ext = priv->ext = calloc(len, sizeof(struct sym_ext));
410 if (!sym->priv) 456 if (!priv->ext)
411 return; 457 return;
412 458
413 sym_ext = sym->priv;
414 start = he->map->unmap_ip(he->map, sym->start); 459 start = he->map->unmap_ip(he->map, sym->start);
415 460
416 for (i = 0; i < len; i++) { 461 for (i = 0; i < len; i++) {
@@ -419,7 +464,7 @@ get_source_line(struct hist_entry *he, int len, const char *filename)
419 u64 offset; 464 u64 offset;
420 FILE *fp; 465 FILE *fp;
421 466
422 sym_ext[i].percent = 100.0 * sym->hist[i] / sym->hist_sum; 467 sym_ext[i].percent = 100.0 * h->ip[i] / h->sum;
423 if (sym_ext[i].percent <= 0.5) 468 if (sym_ext[i].percent <= 0.5)
424 continue; 469 continue;
425 470
@@ -530,7 +575,7 @@ static void annotate_sym(struct hist_entry *he)
530 575
531 pclose(file); 576 pclose(file);
532 if (print_line) 577 if (print_line)
533 free_source_line(sym, len); 578 free_source_line(he, len);
534} 579}
535 580
536static void find_annotations(void) 581static void find_annotations(void)
@@ -540,19 +585,23 @@ static void find_annotations(void)
540 585
541 for (nd = rb_first(&output_hists); nd; nd = rb_next(nd)) { 586 for (nd = rb_first(&output_hists); nd; nd = rb_next(nd)) {
542 struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node); 587 struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
588 struct sym_priv *priv;
543 589
544 if (he->sym && he->sym->hist) { 590 if (he->sym == NULL)
545 annotate_sym(he); 591 continue;
546 count++;
547 /*
548 * Since we have a hist_entry per IP for the same
549 * symbol, free he->sym->hist to signal we already
550 * processed this symbol.
551 */
552 free(he->sym->hist);
553 he->sym->hist = NULL;
554 592
555 } 593 priv = dso__sym_priv(he->map->dso, he->sym);
594 if (priv->hist == NULL)
595 continue;
596
597 annotate_sym(he);
598 count++;
599 /*
600 * Since we have a hist_entry per IP for the same symbol, free
601 * he->sym->hist to signal we already processed this symbol.
602 */
603 free(priv->hist);
604 priv->hist = NULL;
556 } 605 }
557 606
558 if (!count) 607 if (!count)
@@ -593,7 +642,7 @@ static int __cmd_annotate(void)
593 exit(0); 642 exit(0);
594 } 643 }
595 644
596 if (load_kernel() < 0) { 645 if (load_kernel(sizeof(struct sym_priv), symbol_filter) < 0) {
597 perror("failed to load kernel symbols"); 646 perror("failed to load kernel symbols");
598 return EXIT_FAILURE; 647 return EXIT_FAILURE;
599 } 648 }