linux/tools/perf/util/callchain.h
Frederic Weisbecker 108553e1f3 perf: Sync callchains with period based hits
Hists have their hits increased by the event period. And this
period based counting is the foundation of all the stats in
perf report.

But callchains still use the raw number of hits, without taking
the period into account. So when we compute the percentage,
absolute based percentages are totally broken, and relative ones
too in the first parent level. Because we pass the number of events
muliplied by their period as the total number of hits to the
callchain filtering, while callchains expect this number to be
the number of raw hits.

perf report -g graph was simply not working, showing no graph unless
the min percent was zero. And even there the percentage of the
branches was always 0. And may be fractal filtering was broken on
the first branch level too.

flat also was broken, but it was hidden because of other breakages.

Anyway fix this by counting using periods on callchains.

Signed-off-by: Frederic 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>
2010-07-08 06:26:56 +02:00

68 lines
1.5 KiB
C

#ifndef __PERF_CALLCHAIN_H
#define __PERF_CALLCHAIN_H
#include "../perf.h"
#include <linux/list.h>
#include <linux/rbtree.h>
#include "event.h"
#include "symbol.h"
enum chain_mode {
CHAIN_NONE,
CHAIN_FLAT,
CHAIN_GRAPH_ABS,
CHAIN_GRAPH_REL
};
struct callchain_node {
struct callchain_node *parent;
struct list_head brothers;
struct list_head children;
struct list_head val;
struct rb_node rb_node; /* to sort nodes in an rbtree */
struct rb_root rb_root; /* sorted tree of children */
unsigned int val_nr;
u64 hit;
u64 children_hit;
};
struct callchain_param;
typedef void (*sort_chain_func_t)(struct rb_root *, struct callchain_node *,
u64, struct callchain_param *);
struct callchain_param {
enum chain_mode mode;
u32 print_limit;
double min_percent;
sort_chain_func_t sort;
};
struct callchain_list {
u64 ip;
struct map_symbol ms;
struct list_head list;
};
static inline void callchain_init(struct callchain_node *node)
{
INIT_LIST_HEAD(&node->brothers);
INIT_LIST_HEAD(&node->children);
INIT_LIST_HEAD(&node->val);
node->parent = NULL;
node->hit = 0;
}
static inline u64 cumul_hits(struct callchain_node *node)
{
return node->hit + node->children_hit;
}
int register_callchain_param(struct callchain_param *param);
int append_chain(struct callchain_node *root, struct ip_callchain *chain,
struct map_symbol *syms, u64 period);
bool ip_callchain__valid(struct ip_callchain *chain, event_t *event);
#endif /* __PERF_CALLCHAIN_H */