aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2009-08-07 01:11:05 -0400
committerIngo Molnar <mingo@elte.hu>2009-08-09 06:54:33 -0400
commit1953287bfe8afcbbd235bd6c42c9df06d52438dc (patch)
tree7428a4f33fe3509d7a705706df4f3c688266e19f
parent836179834833272f89098c6d1e1b89e8e69797c2 (diff)
perf tools: Fix call-chain cumul hit based sub-total (fractal mode)
The callchain fractal mode builds each new total hits in a new branch of profiling by using the parent's hits of the current branch plus the hits of the children. This is wrong, the total hits of a branch should be made of the sum of every children hits, we must ignore the parent hits in this scope. This patch also fixes another mistake with the hit counting. Now the rates are correct. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Pekka Enberg <penberg@cs.helsinki.fi> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--tools/perf/builtin-report.c4
-rw-r--r--tools/perf/util/callchain.c27
-rw-r--r--tools/perf/util/callchain.h7
3 files changed, 24 insertions, 14 deletions
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 8cb58d68a006..da402e186561 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -901,7 +901,7 @@ callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
901 int i; 901 int i;
902 902
903 if (callchain_param.mode == CHAIN_GRAPH_REL) 903 if (callchain_param.mode == CHAIN_GRAPH_REL)
904 new_total = self->cumul_hit; 904 new_total = self->children_hit;
905 else 905 else
906 new_total = total_samples; 906 new_total = total_samples;
907 907
@@ -930,7 +930,7 @@ callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
930 ret += ipchain__fprintf_graph(fp, chain, depth, 930 ret += ipchain__fprintf_graph(fp, chain, depth,
931 new_depth_mask, i++, 931 new_depth_mask, i++,
932 new_total, 932 new_total,
933 child->cumul_hit); 933 cumul_hits(child));
934 } 934 }
935 ret += callchain__fprintf_graph(fp, child, new_total, 935 ret += callchain__fprintf_graph(fp, child, new_total,
936 depth + 1, 936 depth + 1,
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 9d3c8141b8c1..98c5627f327b 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -26,10 +26,14 @@ rb_insert_callchain(struct rb_root *root, struct callchain_node *chain,
26 struct rb_node **p = &root->rb_node; 26 struct rb_node **p = &root->rb_node;
27 struct rb_node *parent = NULL; 27 struct rb_node *parent = NULL;
28 struct callchain_node *rnode; 28 struct callchain_node *rnode;
29 u64 chain_cumul = cumul_hits(chain);
29 30
30 while (*p) { 31 while (*p) {
32 u64 rnode_cumul;
33
31 parent = *p; 34 parent = *p;
32 rnode = rb_entry(parent, struct callchain_node, rb_node); 35 rnode = rb_entry(parent, struct callchain_node, rb_node);
36 rnode_cumul = cumul_hits(rnode);
33 37
34 switch (mode) { 38 switch (mode) {
35 case CHAIN_FLAT: 39 case CHAIN_FLAT:
@@ -40,7 +44,7 @@ rb_insert_callchain(struct rb_root *root, struct callchain_node *chain,
40 break; 44 break;
41 case CHAIN_GRAPH_ABS: /* Falldown */ 45 case CHAIN_GRAPH_ABS: /* Falldown */
42 case CHAIN_GRAPH_REL: 46 case CHAIN_GRAPH_REL:
43 if (rnode->cumul_hit < chain->cumul_hit) 47 if (rnode_cumul < chain_cumul)
44 p = &(*p)->rb_left; 48 p = &(*p)->rb_left;
45 else 49 else
46 p = &(*p)->rb_right; 50 p = &(*p)->rb_right;
@@ -87,7 +91,7 @@ static void __sort_chain_graph_abs(struct callchain_node *node,
87 91
88 chain_for_each_child(child, node) { 92 chain_for_each_child(child, node) {
89 __sort_chain_graph_abs(child, min_hit); 93 __sort_chain_graph_abs(child, min_hit);
90 if (child->cumul_hit >= min_hit) 94 if (cumul_hits(child) >= min_hit)
91 rb_insert_callchain(&node->rb_root, child, 95 rb_insert_callchain(&node->rb_root, child,
92 CHAIN_GRAPH_ABS); 96 CHAIN_GRAPH_ABS);
93 } 97 }
@@ -108,11 +112,11 @@ static void __sort_chain_graph_rel(struct callchain_node *node,
108 u64 min_hit; 112 u64 min_hit;
109 113
110 node->rb_root = RB_ROOT; 114 node->rb_root = RB_ROOT;
111 min_hit = node->cumul_hit * min_percent / 100.0; 115 min_hit = node->children_hit * min_percent / 100.0;
112 116
113 chain_for_each_child(child, node) { 117 chain_for_each_child(child, node) {
114 __sort_chain_graph_rel(child, min_percent); 118 __sort_chain_graph_rel(child, min_percent);
115 if (child->cumul_hit >= min_hit) 119 if (cumul_hits(child) >= min_hit)
116 rb_insert_callchain(&node->rb_root, child, 120 rb_insert_callchain(&node->rb_root, child,
117 CHAIN_GRAPH_REL); 121 CHAIN_GRAPH_REL);
118 } 122 }
@@ -211,7 +215,8 @@ add_child(struct callchain_node *parent, struct ip_callchain *chain,
211 new = create_child(parent, false); 215 new = create_child(parent, false);
212 fill_node(new, chain, start, syms); 216 fill_node(new, chain, start, syms);
213 217
214 new->cumul_hit = new->hit = 1; 218 new->children_hit = 0;
219 new->hit = 1;
215} 220}
216 221
217/* 222/*
@@ -241,7 +246,8 @@ split_add_child(struct callchain_node *parent, struct ip_callchain *chain,
241 246
242 /* split the hits */ 247 /* split the hits */
243 new->hit = parent->hit; 248 new->hit = parent->hit;
244 new->cumul_hit = parent->cumul_hit; 249 new->children_hit = parent->children_hit;
250 parent->children_hit = cumul_hits(new);
245 new->val_nr = parent->val_nr - idx_local; 251 new->val_nr = parent->val_nr - idx_local;
246 parent->val_nr = idx_local; 252 parent->val_nr = idx_local;
247 253
@@ -249,6 +255,7 @@ split_add_child(struct callchain_node *parent, struct ip_callchain *chain,
249 if (idx_total < chain->nr) { 255 if (idx_total < chain->nr) {
250 parent->hit = 0; 256 parent->hit = 0;
251 add_child(parent, chain, idx_total, syms); 257 add_child(parent, chain, idx_total, syms);
258 parent->children_hit++;
252 } else { 259 } else {
253 parent->hit = 1; 260 parent->hit = 1;
254 } 261 }
@@ -269,13 +276,13 @@ __append_chain_children(struct callchain_node *root, struct ip_callchain *chain,
269 unsigned int ret = __append_chain(rnode, chain, start, syms); 276 unsigned int ret = __append_chain(rnode, chain, start, syms);
270 277
271 if (!ret) 278 if (!ret)
272 goto cumul; 279 goto inc_children_hit;
273 } 280 }
274 /* nothing in children, add to the current node */ 281 /* nothing in children, add to the current node */
275 add_child(root, chain, start, syms); 282 add_child(root, chain, start, syms);
276 283
277cumul: 284inc_children_hit:
278 root->cumul_hit++; 285 root->children_hit++;
279} 286}
280 287
281static int 288static int
@@ -317,8 +324,6 @@ __append_chain(struct callchain_node *root, struct ip_callchain *chain,
317 /* we match 100% of the path, increment the hit */ 324 /* we match 100% of the path, increment the hit */
318 if (i - start == root->val_nr && i == chain->nr) { 325 if (i - start == root->val_nr && i == chain->nr) {
319 root->hit++; 326 root->hit++;
320 root->cumul_hit++;
321
322 return 0; 327 return 0;
323 } 328 }
324 329
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 7812122bea1d..b2d128e07c88 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -21,7 +21,7 @@ struct callchain_node {
21 struct rb_root rb_root; /* sorted tree of children */ 21 struct rb_root rb_root; /* sorted tree of children */
22 unsigned int val_nr; 22 unsigned int val_nr;
23 u64 hit; 23 u64 hit;
24 u64 cumul_hit; /* hit + hits of children */ 24 u64 children_hit;
25}; 25};
26 26
27struct callchain_param; 27struct callchain_param;
@@ -48,6 +48,11 @@ static inline void callchain_init(struct callchain_node *node)
48 INIT_LIST_HEAD(&node->val); 48 INIT_LIST_HEAD(&node->val);
49} 49}
50 50
51static inline u64 cumul_hits(struct callchain_node *node)
52{
53 return node->hit + node->children_hit;
54}
55
51int register_callchain_param(struct callchain_param *param); 56int register_callchain_param(struct callchain_param *param);
52void append_chain(struct callchain_node *root, struct ip_callchain *chain, 57void append_chain(struct callchain_node *root, struct ip_callchain *chain,
53 struct symbol **syms); 58 struct symbol **syms);