diff options
Diffstat (limited to 'tools/perf/util')
-rw-r--r-- | tools/perf/util/callchain.c | 84 | ||||
-rw-r--r-- | tools/perf/util/callchain.h | 21 |
2 files changed, 84 insertions, 21 deletions
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index 5d244afb7cdf..9d3c8141b8c1 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c | |||
@@ -32,13 +32,14 @@ rb_insert_callchain(struct rb_root *root, struct callchain_node *chain, | |||
32 | rnode = rb_entry(parent, struct callchain_node, rb_node); | 32 | rnode = rb_entry(parent, struct callchain_node, rb_node); |
33 | 33 | ||
34 | switch (mode) { | 34 | switch (mode) { |
35 | case FLAT: | 35 | case CHAIN_FLAT: |
36 | if (rnode->hit < chain->hit) | 36 | if (rnode->hit < chain->hit) |
37 | p = &(*p)->rb_left; | 37 | p = &(*p)->rb_left; |
38 | else | 38 | else |
39 | p = &(*p)->rb_right; | 39 | p = &(*p)->rb_right; |
40 | break; | 40 | break; |
41 | case GRAPH: | 41 | case CHAIN_GRAPH_ABS: /* Falldown */ |
42 | case CHAIN_GRAPH_REL: | ||
42 | if (rnode->cumul_hit < chain->cumul_hit) | 43 | if (rnode->cumul_hit < chain->cumul_hit) |
43 | p = &(*p)->rb_left; | 44 | p = &(*p)->rb_left; |
44 | else | 45 | else |
@@ -53,43 +54,96 @@ rb_insert_callchain(struct rb_root *root, struct callchain_node *chain, | |||
53 | rb_insert_color(&chain->rb_node, root); | 54 | rb_insert_color(&chain->rb_node, root); |
54 | } | 55 | } |
55 | 56 | ||
57 | static void | ||
58 | __sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node, | ||
59 | u64 min_hit) | ||
60 | { | ||
61 | struct callchain_node *child; | ||
62 | |||
63 | chain_for_each_child(child, node) | ||
64 | __sort_chain_flat(rb_root, child, min_hit); | ||
65 | |||
66 | if (node->hit && node->hit >= min_hit) | ||
67 | rb_insert_callchain(rb_root, node, CHAIN_FLAT); | ||
68 | } | ||
69 | |||
56 | /* | 70 | /* |
57 | * Once we get every callchains from the stream, we can now | 71 | * Once we get every callchains from the stream, we can now |
58 | * sort them by hit | 72 | * sort them by hit |
59 | */ | 73 | */ |
60 | void sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node, | 74 | static void |
61 | u64 min_hit) | 75 | sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node, |
76 | u64 min_hit, struct callchain_param *param __used) | ||
77 | { | ||
78 | __sort_chain_flat(rb_root, node, min_hit); | ||
79 | } | ||
80 | |||
81 | static void __sort_chain_graph_abs(struct callchain_node *node, | ||
82 | u64 min_hit) | ||
62 | { | 83 | { |
63 | struct callchain_node *child; | 84 | struct callchain_node *child; |
64 | 85 | ||
65 | chain_for_each_child(child, node) | 86 | node->rb_root = RB_ROOT; |
66 | sort_chain_flat(rb_root, child, min_hit); | ||
67 | 87 | ||
68 | if (node->hit && node->hit >= min_hit) | 88 | chain_for_each_child(child, node) { |
69 | rb_insert_callchain(rb_root, node, FLAT); | 89 | __sort_chain_graph_abs(child, min_hit); |
90 | if (child->cumul_hit >= min_hit) | ||
91 | rb_insert_callchain(&node->rb_root, child, | ||
92 | CHAIN_GRAPH_ABS); | ||
93 | } | ||
94 | } | ||
95 | |||
96 | static void | ||
97 | sort_chain_graph_abs(struct rb_root *rb_root, struct callchain_node *chain_root, | ||
98 | u64 min_hit, struct callchain_param *param __used) | ||
99 | { | ||
100 | __sort_chain_graph_abs(chain_root, min_hit); | ||
101 | rb_root->rb_node = chain_root->rb_root.rb_node; | ||
70 | } | 102 | } |
71 | 103 | ||
72 | static void __sort_chain_graph(struct callchain_node *node, u64 min_hit) | 104 | static void __sort_chain_graph_rel(struct callchain_node *node, |
105 | double min_percent) | ||
73 | { | 106 | { |
74 | struct callchain_node *child; | 107 | struct callchain_node *child; |
108 | u64 min_hit; | ||
75 | 109 | ||
76 | node->rb_root = RB_ROOT; | 110 | node->rb_root = RB_ROOT; |
111 | min_hit = node->cumul_hit * min_percent / 100.0; | ||
77 | 112 | ||
78 | chain_for_each_child(child, node) { | 113 | chain_for_each_child(child, node) { |
79 | __sort_chain_graph(child, min_hit); | 114 | __sort_chain_graph_rel(child, min_percent); |
80 | if (child->cumul_hit >= min_hit) | 115 | if (child->cumul_hit >= min_hit) |
81 | rb_insert_callchain(&node->rb_root, child, GRAPH); | 116 | rb_insert_callchain(&node->rb_root, child, |
117 | CHAIN_GRAPH_REL); | ||
82 | } | 118 | } |
83 | } | 119 | } |
84 | 120 | ||
85 | void | 121 | static void |
86 | sort_chain_graph(struct rb_root *rb_root, struct callchain_node *chain_root, | 122 | sort_chain_graph_rel(struct rb_root *rb_root, struct callchain_node *chain_root, |
87 | u64 min_hit) | 123 | u64 min_hit __used, struct callchain_param *param) |
88 | { | 124 | { |
89 | __sort_chain_graph(chain_root, min_hit); | 125 | __sort_chain_graph_rel(chain_root, param->min_percent); |
90 | rb_root->rb_node = chain_root->rb_root.rb_node; | 126 | rb_root->rb_node = chain_root->rb_root.rb_node; |
91 | } | 127 | } |
92 | 128 | ||
129 | int register_callchain_param(struct callchain_param *param) | ||
130 | { | ||
131 | switch (param->mode) { | ||
132 | case CHAIN_GRAPH_ABS: | ||
133 | param->sort = sort_chain_graph_abs; | ||
134 | break; | ||
135 | case CHAIN_GRAPH_REL: | ||
136 | param->sort = sort_chain_graph_rel; | ||
137 | break; | ||
138 | case CHAIN_FLAT: | ||
139 | param->sort = sort_chain_flat; | ||
140 | break; | ||
141 | default: | ||
142 | return -1; | ||
143 | } | ||
144 | return 0; | ||
145 | } | ||
146 | |||
93 | /* | 147 | /* |
94 | * Create a child for a parent. If inherit_children, then the new child | 148 | * Create a child for a parent. If inherit_children, then the new child |
95 | * will become the new parent of it's parent children | 149 | * will become the new parent of it's parent children |
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index f3e4776e7430..7812122bea1d 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h | |||
@@ -7,8 +7,9 @@ | |||
7 | #include "symbol.h" | 7 | #include "symbol.h" |
8 | 8 | ||
9 | enum chain_mode { | 9 | enum chain_mode { |
10 | FLAT, | 10 | CHAIN_FLAT, |
11 | GRAPH | 11 | CHAIN_GRAPH_ABS, |
12 | CHAIN_GRAPH_REL | ||
12 | }; | 13 | }; |
13 | 14 | ||
14 | struct callchain_node { | 15 | struct callchain_node { |
@@ -23,6 +24,17 @@ struct callchain_node { | |||
23 | u64 cumul_hit; /* hit + hits of children */ | 24 | u64 cumul_hit; /* hit + hits of children */ |
24 | }; | 25 | }; |
25 | 26 | ||
27 | struct callchain_param; | ||
28 | |||
29 | typedef void (*sort_chain_func_t)(struct rb_root *, struct callchain_node *, | ||
30 | u64, struct callchain_param *); | ||
31 | |||
32 | struct callchain_param { | ||
33 | enum chain_mode mode; | ||
34 | double min_percent; | ||
35 | sort_chain_func_t sort; | ||
36 | }; | ||
37 | |||
26 | struct callchain_list { | 38 | struct callchain_list { |
27 | u64 ip; | 39 | u64 ip; |
28 | struct symbol *sym; | 40 | struct symbol *sym; |
@@ -36,10 +48,7 @@ static inline void callchain_init(struct callchain_node *node) | |||
36 | INIT_LIST_HEAD(&node->val); | 48 | INIT_LIST_HEAD(&node->val); |
37 | } | 49 | } |
38 | 50 | ||
51 | int register_callchain_param(struct callchain_param *param); | ||
39 | void append_chain(struct callchain_node *root, struct ip_callchain *chain, | 52 | void append_chain(struct callchain_node *root, struct ip_callchain *chain, |
40 | struct symbol **syms); | 53 | struct symbol **syms); |
41 | void sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node, | ||
42 | u64 min_hit); | ||
43 | void sort_chain_graph(struct rb_root *rb_root, struct callchain_node *node, | ||
44 | u64 min_hit); | ||
45 | #endif | 54 | #endif |