perf diff: Start moving to support matching more than two hists
We want to match more than two hists, so that we can match more than two
perf.data files and moreover, match hist_entries (buckets) in multiple
events in a group.
So the "baseline"/"leader" will instead of a ->pair pointer, use a
list_head, that will link to the pairs and hists__match use it.
Following that perf_evlist__link will link the hists in its evsel
groups.
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-2kbmzepoi544ygj9godseqpv@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 380683d..8a9db38 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -154,7 +154,7 @@
double perf_diff__compute_delta(struct hist_entry *he)
{
- struct hist_entry *pair = he->pair;
+ struct hist_entry *pair = hist_entry__next_pair(he);
double new_percent = get_period_percent(he, he->stat.period);
double old_percent = pair ? get_period_percent(pair, pair->stat.period) : 0.0;
@@ -165,7 +165,7 @@
double perf_diff__compute_ratio(struct hist_entry *he)
{
- struct hist_entry *pair = he->pair;
+ struct hist_entry *pair = hist_entry__next_pair(he);
double new_period = he->stat.period;
double old_period = pair ? pair->stat.period : 0;
@@ -176,7 +176,7 @@
s64 perf_diff__compute_wdiff(struct hist_entry *he)
{
- struct hist_entry *pair = he->pair;
+ struct hist_entry *pair = hist_entry__next_pair(he);
u64 new_period = he->stat.period;
u64 old_period = pair ? pair->stat.period : 0;
@@ -193,7 +193,7 @@
static int formula_delta(struct hist_entry *he, char *buf, size_t size)
{
- struct hist_entry *pair = he->pair;
+ struct hist_entry *pair = hist_entry__next_pair(he);
if (!pair)
return -1;
@@ -207,7 +207,7 @@
static int formula_ratio(struct hist_entry *he, char *buf, size_t size)
{
- struct hist_entry *pair = he->pair;
+ struct hist_entry *pair = hist_entry__next_pair(he);
double new_period = he->stat.period;
double old_period = pair ? pair->stat.period : 0;
@@ -219,7 +219,7 @@
static int formula_wdiff(struct hist_entry *he, char *buf, size_t size)
{
- struct hist_entry *pair = he->pair;
+ struct hist_entry *pair = hist_entry__next_pair(he);
u64 new_period = he->stat.period;
u64 old_period = pair ? pair->stat.period : 0;
@@ -359,8 +359,11 @@
struct rb_node *nd;
for (nd = rb_first(&newer->entries); nd; nd = rb_next(nd)) {
- struct hist_entry *pos = rb_entry(nd, struct hist_entry, rb_node);
- pos->pair = hists__find_entry(older, pos);
+ struct hist_entry *pos = rb_entry(nd, struct hist_entry, rb_node),
+ *pair = hists__find_entry(older, pos);
+
+ if (pair)
+ hist__entry_add_pair(pos, pair);
}
}
@@ -402,7 +405,7 @@
struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node);
next = rb_next(&he->rb_node);
- if (!he->pair) {
+ if (!hist_entry__next_pair(he)) {
rb_erase(&he->rb_node, &hists->entries);
hist_entry__free(he);
}
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 4f5f475..aa84130 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -161,7 +161,7 @@
static double baseline_percent(struct hist_entry *he)
{
- struct hist_entry *pair = he->pair;
+ struct hist_entry *pair = hist_entry__next_pair(he);
struct hists *pair_hists = pair ? pair->hists : NULL;
double percent = 0.0;
@@ -179,7 +179,7 @@
{
double percent = baseline_percent(he);
- if (he->pair)
+ if (hist_entry__has_pairs(he))
return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent);
else
return scnprintf(hpp->buf, hpp->size, " ");
@@ -190,7 +190,7 @@
double percent = baseline_percent(he);
const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%";
- if (he->pair || symbol_conf.field_sep)
+ if (hist_entry__has_pairs(he) || symbol_conf.field_sep)
return scnprintf(hpp->buf, hpp->size, fmt, percent);
else
return scnprintf(hpp->buf, hpp->size, " ");
@@ -248,7 +248,7 @@
static int hpp__entry_period_baseline(struct perf_hpp *hpp, struct hist_entry *he)
{
- struct hist_entry *pair = he->pair;
+ struct hist_entry *pair = hist_entry__next_pair(he);
u64 period = pair ? pair->stat.period : 0;
const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%12" PRIu64;
@@ -354,7 +354,7 @@
static int hpp__entry_displ(struct perf_hpp *hpp,
struct hist_entry *he)
{
- struct hist_entry *pair = he->pair;
+ struct hist_entry *pair = hist_entry__next_pair(he);
long displacement = pair ? pair->position - he->position : 0;
const char *fmt = symbol_conf.field_sep ? "%s" : "%6.6s";
char buf[32] = " ";
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index a1b823f..f42de79 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -244,6 +244,8 @@
he->ms.map->referenced = true;
if (symbol_conf.use_callchain)
callchain_init(he->callchain);
+
+ INIT_LIST_HEAD(&he->pairs.node);
}
return he;
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 13761d8..b4e8c3b 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -77,6 +77,10 @@
struct hist_entry {
struct rb_node rb_node_in;
struct rb_node rb_node;
+ union {
+ struct list_head node;
+ struct list_head head;
+ } pairs;
struct he_stat stat;
struct map_symbol ms;
struct thread *thread;
@@ -96,15 +100,30 @@
char *srcline;
struct symbol *parent;
unsigned long position;
- union {
- struct hist_entry *pair;
- struct rb_root sorted_chain;
- };
+ struct rb_root sorted_chain;
struct branch_info *branch_info;
struct hists *hists;
struct callchain_root callchain[0];
};
+static inline bool hist_entry__has_pairs(struct hist_entry *he)
+{
+ return !list_empty(&he->pairs.node);
+}
+
+static inline struct hist_entry *hist_entry__next_pair(struct hist_entry *he)
+{
+ if (hist_entry__has_pairs(he))
+ return list_entry(he->pairs.node.next, struct hist_entry, pairs.node);
+ return NULL;
+}
+
+static inline void hist__entry_add_pair(struct hist_entry *he,
+ struct hist_entry *pair)
+{
+ list_add_tail(&he->pairs.head, &pair->pairs.node);
+}
+
enum sort_type {
SORT_PID,
SORT_COMM,