summaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-diff.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-diff.c')
-rw-r--r--tools/perf/builtin-diff.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 83b8c0f3fb16..fafb7b3f58fb 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -641,6 +641,82 @@ static int process_block_per_sym(struct hist_entry *he)
return 0;
}
+static int block_pair_cmp(struct hist_entry *a, struct hist_entry *b)
+{
+ struct block_info *bi_a = a->block_info;
+ struct block_info *bi_b = b->block_info;
+ int cmp;
+
+ if (!bi_a->sym || !bi_b->sym)
+ return -1;
+
+ cmp = strcmp(bi_a->sym->name, bi_b->sym->name);
+
+ if ((!cmp) && (bi_a->start == bi_b->start) && (bi_a->end == bi_b->end))
+ return 0;
+
+ return -1;
+}
+
+static struct hist_entry *get_block_pair(struct hist_entry *he,
+ struct hists *hists_pair)
+{
+ struct rb_root_cached *root = hists_pair->entries_in;
+ struct rb_node *next = rb_first_cached(root);
+ int cmp;
+
+ while (next != NULL) {
+ struct hist_entry *he_pair = rb_entry(next, struct hist_entry,
+ rb_node_in);
+
+ next = rb_next(&he_pair->rb_node_in);
+
+ cmp = block_pair_cmp(he_pair, he);
+ if (!cmp)
+ return he_pair;
+ }
+
+ return NULL;
+}
+
+static void compute_cycles_diff(struct hist_entry *he,
+ struct hist_entry *pair)
+{
+ pair->diff.computed = true;
+ if (pair->block_info->num && he->block_info->num) {
+ pair->diff.cycles =
+ pair->block_info->cycles_aggr / pair->block_info->num_aggr -
+ he->block_info->cycles_aggr / he->block_info->num_aggr;
+ }
+}
+
+static void block_hists_match(struct hists *hists_base,
+ struct hists *hists_pair)
+{
+ struct rb_root_cached *root = hists_base->entries_in;
+ struct rb_node *next = rb_first_cached(root);
+
+ while (next != NULL) {
+ struct hist_entry *he = rb_entry(next, struct hist_entry,
+ rb_node_in);
+ struct hist_entry *pair = get_block_pair(he, hists_pair);
+
+ next = rb_next(&he->rb_node_in);
+
+ if (pair) {
+ hist_entry__add_pair(pair, he);
+ compute_cycles_diff(he, pair);
+ }
+ }
+}
+
+static int filter_cb(struct hist_entry *he, void *arg __maybe_unused)
+{
+ /* Skip the calculation of column length in output_resort */
+ he->filtered = true;
+ return 0;
+}
+
static void hists__precompute(struct hists *hists)
{
struct rb_root_cached *root;
@@ -653,6 +729,7 @@ static void hists__precompute(struct hists *hists)
next = rb_first_cached(root);
while (next != NULL) {
+ struct block_hist *bh, *pair_bh;
struct hist_entry *he, *pair;
struct data__file *d;
int i;
@@ -681,6 +758,16 @@ static void hists__precompute(struct hists *hists)
break;
case COMPUTE_CYCLES:
process_block_per_sym(pair);
+ bh = container_of(he, struct block_hist, he);
+ pair_bh = container_of(pair, struct block_hist,
+ he);
+
+ if (bh->valid && pair_bh->valid) {
+ block_hists_match(&bh->block_hists,
+ &pair_bh->block_hists);
+ hists__output_resort_cb(&pair_bh->block_hists,
+ NULL, filter_cb);
+ }
break;
default:
BUG_ON(1);