perf hist: Deduplicate cmp/sort/collapse code

Application of cmp/sort/collapse fmt callbacks is duplicated 6 times.
Factor it into a common helper function. NFC.

Signed-off-by: Dmitry Vyukov <dvyukov@google.com>
Link: https://lore.kernel.org/r/84c4b55614e24a344f86ae0db62e8fa8f251f874.1736927981.git.dvyukov@google.com
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
This commit is contained in:
Dmitry Vyukov
2025-01-15 09:00:41 +01:00
committed by Namhyung Kim
parent 4e38f2814f
commit cd57c04c38
2 changed files with 50 additions and 69 deletions

View File

@@ -32,6 +32,9 @@
#include <linux/time64.h>
#include <linux/zalloc.h>
static int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right);
static int64_t hist_entry__collapse(struct hist_entry *left, struct hist_entry *right);
static bool hists__filter_entry_by_dso(struct hists *hists,
struct hist_entry *he);
static bool hists__filter_entry_by_thread(struct hists *hists,
@@ -1292,19 +1295,26 @@ out:
return err;
}
int64_t
hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
static int64_t
hist_entry__cmp_impl(struct perf_hpp_list *hpp_list, struct hist_entry *left,
struct hist_entry *right, unsigned long fn_offset,
bool ignore_dynamic, bool ignore_skipped)
{
struct hists *hists = left->hists;
struct perf_hpp_fmt *fmt;
perf_hpp_fmt_cmp_t *fn;
int64_t cmp = 0;
hists__for_each_sort_list(hists, fmt) {
if (perf_hpp__is_dynamic_entry(fmt) &&
perf_hpp_list__for_each_sort_list(hpp_list, fmt) {
if (ignore_dynamic && perf_hpp__is_dynamic_entry(fmt) &&
!perf_hpp__defined_dynamic_entry(fmt, hists))
continue;
cmp = fmt->cmp(fmt, left, right);
if (ignore_skipped && perf_hpp__should_skip(fmt, hists))
continue;
fn = (void *)fmt + fn_offset;
cmp = (*fn)(fmt, left, right);
if (cmp)
break;
}
@@ -1312,24 +1322,34 @@ hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
return cmp;
}
int64_t
hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
{
return hist_entry__cmp_impl(left->hists->hpp_list, left, right,
offsetof(struct perf_hpp_fmt, cmp), true, false);
}
static int64_t
hist_entry__sort(struct hist_entry *left, struct hist_entry *right)
{
return hist_entry__cmp_impl(left->hists->hpp_list, left, right,
offsetof(struct perf_hpp_fmt, sort), false, true);
}
int64_t
hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
{
struct hists *hists = left->hists;
struct perf_hpp_fmt *fmt;
int64_t cmp = 0;
return hist_entry__cmp_impl(left->hists->hpp_list, left, right,
offsetof(struct perf_hpp_fmt, collapse), true, false);
}
hists__for_each_sort_list(hists, fmt) {
if (perf_hpp__is_dynamic_entry(fmt) &&
!perf_hpp__defined_dynamic_entry(fmt, hists))
continue;
cmp = fmt->collapse(fmt, left, right);
if (cmp)
break;
}
return cmp;
static int64_t
hist_entry__collapse_hierarchy(struct perf_hpp_list *hpp_list,
struct hist_entry *left,
struct hist_entry *right)
{
return hist_entry__cmp_impl(hpp_list, left, right,
offsetof(struct perf_hpp_fmt, collapse), false, false);
}
void hist_entry__delete(struct hist_entry *he)
@@ -1503,14 +1523,7 @@ static struct hist_entry *hierarchy_insert_entry(struct hists *hists,
while (*p != NULL) {
parent = *p;
iter = rb_entry(parent, struct hist_entry, rb_node_in);
cmp = 0;
perf_hpp_list__for_each_sort_list(hpp_list, fmt) {
cmp = fmt->collapse(fmt, iter, he);
if (cmp)
break;
}
cmp = hist_entry__collapse_hierarchy(hpp_list, iter, he);
if (!cmp) {
he_stat__add_stat(&iter->stat, &he->stat);
return iter;
@@ -1730,24 +1743,6 @@ int hists__collapse_resort(struct hists *hists, struct ui_progress *prog)
return 0;
}
static int64_t hist_entry__sort(struct hist_entry *a, struct hist_entry *b)
{
struct hists *hists = a->hists;
struct perf_hpp_fmt *fmt;
int64_t cmp = 0;
hists__for_each_sort_list(hists, fmt) {
if (perf_hpp__should_skip(fmt, a->hists))
continue;
cmp = fmt->sort(fmt, a, b);
if (cmp)
break;
}
return cmp;
}
static void hists__reset_filter_stats(struct hists *hists)
{
hists->nr_non_filtered_entries = 0;
@@ -2449,21 +2444,15 @@ static struct hist_entry *add_dummy_hierarchy_entry(struct hists *hists,
struct rb_node **p;
struct rb_node *parent = NULL;
struct hist_entry *he;
struct perf_hpp_fmt *fmt;
bool leftmost = true;
p = &root->rb_root.rb_node;
while (*p != NULL) {
int64_t cmp = 0;
int64_t cmp;
parent = *p;
he = rb_entry(parent, struct hist_entry, rb_node_in);
perf_hpp_list__for_each_sort_list(he->hpp_list, fmt) {
cmp = fmt->collapse(fmt, he, pair);
if (cmp)
break;
}
cmp = hist_entry__collapse_hierarchy(he->hpp_list, he, pair);
if (!cmp)
goto out;
@@ -2521,16 +2510,10 @@ static struct hist_entry *hists__find_hierarchy_entry(struct rb_root_cached *roo
while (n) {
struct hist_entry *iter;
struct perf_hpp_fmt *fmt;
int64_t cmp = 0;
int64_t cmp;
iter = rb_entry(n, struct hist_entry, rb_node_in);
perf_hpp_list__for_each_sort_list(he->hpp_list, fmt) {
cmp = fmt->collapse(fmt, iter, he);
if (cmp)
break;
}
cmp = hist_entry__collapse_hierarchy(he->hpp_list, iter, he);
if (cmp < 0)
n = n->rb_left;
else if (cmp > 0)

View File

@@ -342,8 +342,6 @@ int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al,
struct perf_hpp;
struct perf_hpp_fmt;
int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right);
int64_t hist_entry__collapse(struct hist_entry *left, struct hist_entry *right);
int hist_entry__transaction_len(void);
int hist_entry__sort_snprintf(struct hist_entry *he, char *bf, size_t size,
struct hists *hists);
@@ -452,6 +450,9 @@ struct perf_hpp {
bool skip;
};
typedef int64_t (*perf_hpp_fmt_cmp_t)(
struct perf_hpp_fmt *, struct hist_entry *, struct hist_entry *);
struct perf_hpp_fmt {
const char *name;
int (*header)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
@@ -463,12 +464,9 @@ struct perf_hpp_fmt {
struct hist_entry *he);
int (*entry)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
struct hist_entry *he);
int64_t (*cmp)(struct perf_hpp_fmt *fmt,
struct hist_entry *a, struct hist_entry *b);
int64_t (*collapse)(struct perf_hpp_fmt *fmt,
struct hist_entry *a, struct hist_entry *b);
int64_t (*sort)(struct perf_hpp_fmt *fmt,
struct hist_entry *a, struct hist_entry *b);
perf_hpp_fmt_cmp_t cmp;
perf_hpp_fmt_cmp_t collapse;
perf_hpp_fmt_cmp_t sort;
bool (*equal)(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b);
void (*free)(struct perf_hpp_fmt *fmt);