aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2009-06-26 10:28:01 -0400
committerIngo Molnar <mingo@elte.hu>2009-06-26 10:47:01 -0400
commitf55c555226b1010b249730ec6b232e5470286950 (patch)
tree27523398f7d2487e06532245cc6ed745a611ccf0 /tools/perf
parent8cb76d99d715741637b6d0884f389e17e9cb05d2 (diff)
perf report: Print sorted callchains per histogram entries
Use the newly created callchains radix tree to gather the chains stats from the recorded events and then print the callchains for all of them, sorted by hits, using the "-c" parameter with perf report. Example: 66.15% [k] atm_clip_exit 63.08% 0xffffffffffffff80 0xffffffff810196a8 0xffffffff810c14c8 0xffffffff8101a79c 0xffffffff810194f3 0xffffffff8106ab7f 0xffffffff8106abe5 0xffffffff8106acde 0xffffffff8100d94b 0xffffffff8153e7ea [...] 1.54% 0xffffffffffffff80 0xffffffff810196a8 0xffffffff810c14c8 0xffffffff8101a79c [...] Symbols are not yet resolved. 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: <1246026481-8314-3-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/builtin-report.c82
1 files changed, 71 insertions, 11 deletions
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 28d1cb2127e9..ed391db9e0f8 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -15,6 +15,7 @@
15#include "util/rbtree.h" 15#include "util/rbtree.h"
16#include "util/symbol.h" 16#include "util/symbol.h"
17#include "util/string.h" 17#include "util/string.h"
18#include "util/callchain.h"
18 19
19#include "perf.h" 20#include "perf.h"
20#include "util/header.h" 21#include "util/header.h"
@@ -52,6 +53,7 @@ static char *parent_pattern = default_parent_pattern;
52static regex_t parent_regex; 53static regex_t parent_regex;
53 54
54static int exclude_other = 1; 55static int exclude_other = 1;
56static int callchain;
55 57
56static u64 sample_type; 58static u64 sample_type;
57 59
@@ -488,17 +490,19 @@ static size_t threads__fprintf(FILE *fp)
488static struct rb_root hist; 490static struct rb_root hist;
489 491
490struct hist_entry { 492struct hist_entry {
491 struct rb_node rb_node; 493 struct rb_node rb_node;
492 494
493 struct thread *thread; 495 struct thread *thread;
494 struct map *map; 496 struct map *map;
495 struct dso *dso; 497 struct dso *dso;
496 struct symbol *sym; 498 struct symbol *sym;
497 struct symbol *parent; 499 struct symbol *parent;
498 u64 ip; 500 u64 ip;
499 char level; 501 char level;
500 502 struct callchain_node callchain;
501 u64 count; 503 struct rb_root sorted_chain;
504
505 u64 count;
502}; 506};
503 507
504/* 508/*
@@ -769,6 +773,48 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
769} 773}
770 774
771static size_t 775static size_t
776callchain__fprintf(FILE *fp, struct callchain_node *self, u64 total_samples)
777{
778 struct callchain_list *chain;
779 size_t ret = 0;
780
781 if (!self)
782 return 0;
783
784 ret += callchain__fprintf(fp, self->parent, total_samples);
785
786
787 list_for_each_entry(chain, &self->val, list)
788 ret += fprintf(fp, " %p\n", (void *)chain->ip);
789
790 return ret;
791}
792
793static size_t
794hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self,
795 u64 total_samples)
796{
797 struct rb_node *rb_node;
798 struct callchain_node *chain;
799 size_t ret = 0;
800
801 rb_node = rb_first(&self->sorted_chain);
802 while (rb_node) {
803 double percent;
804
805 chain = rb_entry(rb_node, struct callchain_node, rb_node);
806 percent = chain->hit * 100.0 / total_samples;
807 ret += fprintf(fp, " %6.2f%%\n", percent);
808 ret += callchain__fprintf(fp, chain, total_samples);
809 ret += fprintf(fp, "\n");
810 rb_node = rb_next(rb_node);
811 }
812
813 return ret;
814}
815
816
817static size_t
772hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples) 818hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples)
773{ 819{
774 struct sort_entry *se; 820 struct sort_entry *se;
@@ -808,6 +854,9 @@ hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples)
808 854
809 ret += fprintf(fp, "\n"); 855 ret += fprintf(fp, "\n");
810 856
857 if (callchain)
858 hist_entry_callchain__fprintf(fp, self, total_samples);
859
811 return ret; 860 return ret;
812} 861}
813 862
@@ -892,6 +941,7 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
892 .level = level, 941 .level = level,
893 .count = count, 942 .count = count,
894 .parent = NULL, 943 .parent = NULL,
944 .sorted_chain = RB_ROOT
895 }; 945 };
896 int cmp; 946 int cmp;
897 947
@@ -934,6 +984,8 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
934 984
935 if (!cmp) { 985 if (!cmp) {
936 he->count += count; 986 he->count += count;
987 if (callchain)
988 append_chain(&he->callchain, chain);
937 return 0; 989 return 0;
938 } 990 }
939 991
@@ -947,6 +999,10 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
947 if (!he) 999 if (!he)
948 return -ENOMEM; 1000 return -ENOMEM;
949 *he = entry; 1001 *he = entry;
1002 if (callchain) {
1003 callchain_init(&he->callchain);
1004 append_chain(&he->callchain, chain);
1005 }
950 rb_link_node(&he->rb_node, parent, p); 1006 rb_link_node(&he->rb_node, parent, p);
951 rb_insert_color(&he->rb_node, &hist); 1007 rb_insert_color(&he->rb_node, &hist);
952 1008
@@ -1023,6 +1079,9 @@ static void output__insert_entry(struct hist_entry *he)
1023 struct rb_node *parent = NULL; 1079 struct rb_node *parent = NULL;
1024 struct hist_entry *iter; 1080 struct hist_entry *iter;
1025 1081
1082 if (callchain)
1083 sort_chain_to_rbtree(&he->sorted_chain, &he->callchain);
1084
1026 while (*p != NULL) { 1085 while (*p != NULL) {
1027 parent = *p; 1086 parent = *p;
1028 iter = rb_entry(parent, struct hist_entry, rb_node); 1087 iter = rb_entry(parent, struct hist_entry, rb_node);
@@ -1599,6 +1658,7 @@ static const struct option options[] = {
1599 "regex filter to identify parent, see: '--sort parent'"), 1658 "regex filter to identify parent, see: '--sort parent'"),
1600 OPT_BOOLEAN('x', "exclude-other", &exclude_other, 1659 OPT_BOOLEAN('x', "exclude-other", &exclude_other,
1601 "Only display entries with parent-match"), 1660 "Only display entries with parent-match"),
1661 OPT_BOOLEAN('c', "callchain", &callchain, "Display callchains"),
1602 OPT_END() 1662 OPT_END()
1603}; 1663};
1604 1664