aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/callchain.c
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 /tools/perf/util/callchain.c
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>
Diffstat (limited to 'tools/perf/util/callchain.c')
-rw-r--r--tools/perf/util/callchain.c27
1 files changed, 16 insertions, 11 deletions
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