Skip to content

Commit cd57c04

Browse files
dvyukovnamhyung
authored andcommitted
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>
1 parent 4e38f28 commit cd57c04

File tree

2 files changed

+49
-68
lines changed

2 files changed

+49
-68
lines changed

tools/perf/util/hist.c

Lines changed: 43 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@
3232
#include <linux/time64.h>
3333
#include <linux/zalloc.h>
3434

35+
static int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right);
36+
static int64_t hist_entry__collapse(struct hist_entry *left, struct hist_entry *right);
37+
3538
static bool hists__filter_entry_by_dso(struct hists *hists,
3639
struct hist_entry *he);
3740
static bool hists__filter_entry_by_thread(struct hists *hists,
@@ -1292,19 +1295,26 @@ int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al,
12921295
return err;
12931296
}
12941297

1295-
int64_t
1296-
hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
1298+
static int64_t
1299+
hist_entry__cmp_impl(struct perf_hpp_list *hpp_list, struct hist_entry *left,
1300+
struct hist_entry *right, unsigned long fn_offset,
1301+
bool ignore_dynamic, bool ignore_skipped)
12971302
{
12981303
struct hists *hists = left->hists;
12991304
struct perf_hpp_fmt *fmt;
1305+
perf_hpp_fmt_cmp_t *fn;
13001306
int64_t cmp = 0;
13011307

1302-
hists__for_each_sort_list(hists, fmt) {
1303-
if (perf_hpp__is_dynamic_entry(fmt) &&
1308+
perf_hpp_list__for_each_sort_list(hpp_list, fmt) {
1309+
if (ignore_dynamic && perf_hpp__is_dynamic_entry(fmt) &&
13041310
!perf_hpp__defined_dynamic_entry(fmt, hists))
13051311
continue;
13061312

1307-
cmp = fmt->cmp(fmt, left, right);
1313+
if (ignore_skipped && perf_hpp__should_skip(fmt, hists))
1314+
continue;
1315+
1316+
fn = (void *)fmt + fn_offset;
1317+
cmp = (*fn)(fmt, left, right);
13081318
if (cmp)
13091319
break;
13101320
}
@@ -1313,23 +1323,33 @@ hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
13131323
}
13141324

13151325
int64_t
1316-
hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
1326+
hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
13171327
{
1318-
struct hists *hists = left->hists;
1319-
struct perf_hpp_fmt *fmt;
1320-
int64_t cmp = 0;
1328+
return hist_entry__cmp_impl(left->hists->hpp_list, left, right,
1329+
offsetof(struct perf_hpp_fmt, cmp), true, false);
1330+
}
13211331

1322-
hists__for_each_sort_list(hists, fmt) {
1323-
if (perf_hpp__is_dynamic_entry(fmt) &&
1324-
!perf_hpp__defined_dynamic_entry(fmt, hists))
1325-
continue;
1332+
static int64_t
1333+
hist_entry__sort(struct hist_entry *left, struct hist_entry *right)
1334+
{
1335+
return hist_entry__cmp_impl(left->hists->hpp_list, left, right,
1336+
offsetof(struct perf_hpp_fmt, sort), false, true);
1337+
}
13261338

1327-
cmp = fmt->collapse(fmt, left, right);
1328-
if (cmp)
1329-
break;
1330-
}
1339+
int64_t
1340+
hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
1341+
{
1342+
return hist_entry__cmp_impl(left->hists->hpp_list, left, right,
1343+
offsetof(struct perf_hpp_fmt, collapse), true, false);
1344+
}
13311345

1332-
return cmp;
1346+
static int64_t
1347+
hist_entry__collapse_hierarchy(struct perf_hpp_list *hpp_list,
1348+
struct hist_entry *left,
1349+
struct hist_entry *right)
1350+
{
1351+
return hist_entry__cmp_impl(hpp_list, left, right,
1352+
offsetof(struct perf_hpp_fmt, collapse), false, false);
13331353
}
13341354

13351355
void hist_entry__delete(struct hist_entry *he)
@@ -1503,14 +1523,7 @@ static struct hist_entry *hierarchy_insert_entry(struct hists *hists,
15031523
while (*p != NULL) {
15041524
parent = *p;
15051525
iter = rb_entry(parent, struct hist_entry, rb_node_in);
1506-
1507-
cmp = 0;
1508-
perf_hpp_list__for_each_sort_list(hpp_list, fmt) {
1509-
cmp = fmt->collapse(fmt, iter, he);
1510-
if (cmp)
1511-
break;
1512-
}
1513-
1526+
cmp = hist_entry__collapse_hierarchy(hpp_list, iter, he);
15141527
if (!cmp) {
15151528
he_stat__add_stat(&iter->stat, &he->stat);
15161529
return iter;
@@ -1730,24 +1743,6 @@ int hists__collapse_resort(struct hists *hists, struct ui_progress *prog)
17301743
return 0;
17311744
}
17321745

1733-
static int64_t hist_entry__sort(struct hist_entry *a, struct hist_entry *b)
1734-
{
1735-
struct hists *hists = a->hists;
1736-
struct perf_hpp_fmt *fmt;
1737-
int64_t cmp = 0;
1738-
1739-
hists__for_each_sort_list(hists, fmt) {
1740-
if (perf_hpp__should_skip(fmt, a->hists))
1741-
continue;
1742-
1743-
cmp = fmt->sort(fmt, a, b);
1744-
if (cmp)
1745-
break;
1746-
}
1747-
1748-
return cmp;
1749-
}
1750-
17511746
static void hists__reset_filter_stats(struct hists *hists)
17521747
{
17531748
hists->nr_non_filtered_entries = 0;
@@ -2449,21 +2444,15 @@ static struct hist_entry *add_dummy_hierarchy_entry(struct hists *hists,
24492444
struct rb_node **p;
24502445
struct rb_node *parent = NULL;
24512446
struct hist_entry *he;
2452-
struct perf_hpp_fmt *fmt;
24532447
bool leftmost = true;
24542448

24552449
p = &root->rb_root.rb_node;
24562450
while (*p != NULL) {
2457-
int64_t cmp = 0;
2451+
int64_t cmp;
24582452

24592453
parent = *p;
24602454
he = rb_entry(parent, struct hist_entry, rb_node_in);
2461-
2462-
perf_hpp_list__for_each_sort_list(he->hpp_list, fmt) {
2463-
cmp = fmt->collapse(fmt, he, pair);
2464-
if (cmp)
2465-
break;
2466-
}
2455+
cmp = hist_entry__collapse_hierarchy(he->hpp_list, he, pair);
24672456
if (!cmp)
24682457
goto out;
24692458

@@ -2521,16 +2510,10 @@ static struct hist_entry *hists__find_hierarchy_entry(struct rb_root_cached *roo
25212510

25222511
while (n) {
25232512
struct hist_entry *iter;
2524-
struct perf_hpp_fmt *fmt;
2525-
int64_t cmp = 0;
2513+
int64_t cmp;
25262514

25272515
iter = rb_entry(n, struct hist_entry, rb_node_in);
2528-
perf_hpp_list__for_each_sort_list(he->hpp_list, fmt) {
2529-
cmp = fmt->collapse(fmt, iter, he);
2530-
if (cmp)
2531-
break;
2532-
}
2533-
2516+
cmp = hist_entry__collapse_hierarchy(he->hpp_list, iter, he);
25342517
if (cmp < 0)
25352518
n = n->rb_left;
25362519
else if (cmp > 0)

tools/perf/util/hist.h

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -342,8 +342,6 @@ int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al,
342342
struct perf_hpp;
343343
struct perf_hpp_fmt;
344344

345-
int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right);
346-
int64_t hist_entry__collapse(struct hist_entry *left, struct hist_entry *right);
347345
int hist_entry__transaction_len(void);
348346
int hist_entry__sort_snprintf(struct hist_entry *he, char *bf, size_t size,
349347
struct hists *hists);
@@ -452,6 +450,9 @@ struct perf_hpp {
452450
bool skip;
453451
};
454452

453+
typedef int64_t (*perf_hpp_fmt_cmp_t)(
454+
struct perf_hpp_fmt *, struct hist_entry *, struct hist_entry *);
455+
455456
struct perf_hpp_fmt {
456457
const char *name;
457458
int (*header)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
@@ -463,12 +464,9 @@ struct perf_hpp_fmt {
463464
struct hist_entry *he);
464465
int (*entry)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
465466
struct hist_entry *he);
466-
int64_t (*cmp)(struct perf_hpp_fmt *fmt,
467-
struct hist_entry *a, struct hist_entry *b);
468-
int64_t (*collapse)(struct perf_hpp_fmt *fmt,
469-
struct hist_entry *a, struct hist_entry *b);
470-
int64_t (*sort)(struct perf_hpp_fmt *fmt,
471-
struct hist_entry *a, struct hist_entry *b);
467+
perf_hpp_fmt_cmp_t cmp;
468+
perf_hpp_fmt_cmp_t collapse;
469+
perf_hpp_fmt_cmp_t sort;
472470
bool (*equal)(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b);
473471
void (*free)(struct perf_hpp_fmt *fmt);
474472

0 commit comments

Comments
 (0)