提交 d2009c51 编写于 作者: F Frederic Weisbecker

perf: Keep track of the max depth of a callchain

In order to implement callchains collapsing, we need to keep
track of the maximum depth in a histogram tree of callchains.
This way we'll avoid allocating an arbitrary temporary buffer
size on callchain merge time.
Signed-off-by: NFrederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Christoph Hellwig <hch@infradead.org>
上级 f4e7ac0a
...@@ -86,10 +86,10 @@ __sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node, ...@@ -86,10 +86,10 @@ __sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node,
* sort them by hit * sort them by hit
*/ */
static void static void
sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node, sort_chain_flat(struct rb_root *rb_root, struct callchain_root *root,
u64 min_hit, struct callchain_param *param __used) u64 min_hit, struct callchain_param *param __used)
{ {
__sort_chain_flat(rb_root, node, min_hit); __sort_chain_flat(rb_root, &root->node, min_hit);
} }
static void __sort_chain_graph_abs(struct callchain_node *node, static void __sort_chain_graph_abs(struct callchain_node *node,
...@@ -108,11 +108,11 @@ static void __sort_chain_graph_abs(struct callchain_node *node, ...@@ -108,11 +108,11 @@ static void __sort_chain_graph_abs(struct callchain_node *node,
} }
static void static void
sort_chain_graph_abs(struct rb_root *rb_root, struct callchain_node *chain_root, sort_chain_graph_abs(struct rb_root *rb_root, struct callchain_root *chain_root,
u64 min_hit, struct callchain_param *param __used) u64 min_hit, struct callchain_param *param __used)
{ {
__sort_chain_graph_abs(chain_root, min_hit); __sort_chain_graph_abs(&chain_root->node, min_hit);
rb_root->rb_node = chain_root->rb_root.rb_node; rb_root->rb_node = chain_root->node.rb_root.rb_node;
} }
static void __sort_chain_graph_rel(struct callchain_node *node, static void __sort_chain_graph_rel(struct callchain_node *node,
...@@ -133,11 +133,11 @@ static void __sort_chain_graph_rel(struct callchain_node *node, ...@@ -133,11 +133,11 @@ static void __sort_chain_graph_rel(struct callchain_node *node,
} }
static void static void
sort_chain_graph_rel(struct rb_root *rb_root, struct callchain_node *chain_root, sort_chain_graph_rel(struct rb_root *rb_root, struct callchain_root *chain_root,
u64 min_hit __used, struct callchain_param *param) u64 min_hit __used, struct callchain_param *param)
{ {
__sort_chain_graph_rel(chain_root, param->min_percent / 100.0); __sort_chain_graph_rel(&chain_root->node, param->min_percent / 100.0);
rb_root->rb_node = chain_root->rb_root.rb_node; rb_root->rb_node = chain_root->node.rb_root.rb_node;
} }
int register_callchain_param(struct callchain_param *param) int register_callchain_param(struct callchain_param *param)
...@@ -380,7 +380,7 @@ static void filter_context(struct ip_callchain *old, struct resolved_chain *new, ...@@ -380,7 +380,7 @@ static void filter_context(struct ip_callchain *old, struct resolved_chain *new,
} }
int append_chain(struct callchain_node *root, struct ip_callchain *chain, int append_chain(struct callchain_root *root, struct ip_callchain *chain,
struct map_symbol *syms, u64 period) struct map_symbol *syms, u64 period)
{ {
struct resolved_chain *filtered; struct resolved_chain *filtered;
...@@ -398,7 +398,10 @@ int append_chain(struct callchain_node *root, struct ip_callchain *chain, ...@@ -398,7 +398,10 @@ int append_chain(struct callchain_node *root, struct ip_callchain *chain,
if (!filtered->nr) if (!filtered->nr)
goto end; goto end;
__append_chain_children(root, filtered, 0, period); __append_chain_children(&root->node, filtered, 0, period);
if (filtered->nr > root->max_depth)
root->max_depth = filtered->nr;
end: end:
free(filtered); free(filtered);
......
...@@ -26,9 +26,14 @@ struct callchain_node { ...@@ -26,9 +26,14 @@ struct callchain_node {
u64 children_hit; u64 children_hit;
}; };
struct callchain_root {
u64 max_depth;
struct callchain_node node;
};
struct callchain_param; struct callchain_param;
typedef void (*sort_chain_func_t)(struct rb_root *, struct callchain_node *, typedef void (*sort_chain_func_t)(struct rb_root *, struct callchain_root *,
u64, struct callchain_param *); u64, struct callchain_param *);
struct callchain_param { struct callchain_param {
...@@ -44,14 +49,15 @@ struct callchain_list { ...@@ -44,14 +49,15 @@ struct callchain_list {
struct list_head list; struct list_head list;
}; };
static inline void callchain_init(struct callchain_node *node) static inline void callchain_init(struct callchain_root *root)
{ {
INIT_LIST_HEAD(&node->brothers); INIT_LIST_HEAD(&root->node.brothers);
INIT_LIST_HEAD(&node->children); INIT_LIST_HEAD(&root->node.children);
INIT_LIST_HEAD(&node->val); INIT_LIST_HEAD(&root->node.val);
node->parent = NULL; root->node.parent = NULL;
node->hit = 0; root->node.hit = 0;
root->max_depth = 0;
} }
static inline u64 cumul_hits(struct callchain_node *node) static inline u64 cumul_hits(struct callchain_node *node)
...@@ -60,7 +66,7 @@ static inline u64 cumul_hits(struct callchain_node *node) ...@@ -60,7 +66,7 @@ static inline u64 cumul_hits(struct callchain_node *node)
} }
int register_callchain_param(struct callchain_param *param); int register_callchain_param(struct callchain_param *param);
int append_chain(struct callchain_node *root, struct ip_callchain *chain, int append_chain(struct callchain_root *root, struct ip_callchain *chain,
struct map_symbol *syms, u64 period); struct map_symbol *syms, u64 period);
bool ip_callchain__valid(struct ip_callchain *chain, const event_t *event); bool ip_callchain__valid(struct ip_callchain *chain, const event_t *event);
......
...@@ -87,7 +87,7 @@ static void hist_entry__add_cpumode_period(struct hist_entry *self, ...@@ -87,7 +87,7 @@ static void hist_entry__add_cpumode_period(struct hist_entry *self,
static struct hist_entry *hist_entry__new(struct hist_entry *template) static struct hist_entry *hist_entry__new(struct hist_entry *template)
{ {
size_t callchain_size = symbol_conf.use_callchain ? sizeof(struct callchain_node) : 0; size_t callchain_size = symbol_conf.use_callchain ? sizeof(struct callchain_root) : 0;
struct hist_entry *self = malloc(sizeof(*self) + callchain_size); struct hist_entry *self = malloc(sizeof(*self) + callchain_size);
if (self != NULL) { if (self != NULL) {
......
...@@ -70,7 +70,7 @@ struct hist_entry { ...@@ -70,7 +70,7 @@ struct hist_entry {
struct hist_entry *pair; struct hist_entry *pair;
struct rb_root sorted_chain; struct rb_root sorted_chain;
}; };
struct callchain_node callchain[0]; struct callchain_root callchain[0];
}; };
enum sort_type { enum sort_type {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册