perf pmu: Sort and remove duplicates using JSON PMU name
authorIan Rogers <irogers@google.com>
Thu, 6 Apr 2023 23:52:56 +0000 (16:52 -0700)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 7 Apr 2023 00:54:03 +0000 (21:54 -0300)
We may have a lot of copies of a particular uncore PMU, such as
uncore_cha_0 to uncore_cha_59 on Intel sapphirerapids.

The JSON events may match each of PMUs and so the events are copied to
it.

In 'perf list' this means we see the same JSON event 60 times as events
on different PMUs don't have duplicates removed.

There are 284 uncore_cha events on sapphirerapids.

Rather than use the PMU's name to sort and remove duplicates, use the
JSON PMU name.

This reduces the 60 copies back down to 1 and has the side effect of
speeding things like the "perf all PMU test" shell test.

Signed-off-by: Ian Rogers <irogers@google.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@arm.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ravi Bangoria <ravi.bangoria@amd.com>
Cc: Rob Herring <robh@kernel.org>
Cc: Sean Christopherson <seanjc@google.com>
Cc: Suzuki Poulouse <suzuki.poulose@arm.com>
Link: https://lore.kernel.org/r/20230406235256.2768773-1-irogers@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/pmu.c

index 2e4f60b..91cccfb 100644 (file)
@@ -1574,7 +1574,7 @@ static int cmp_sevent(const void *a, const void *b)
 {
        const struct sevent *as = a;
        const struct sevent *bs = b;
-       const char *a_pmu_name, *b_pmu_name;
+       const char *a_pmu_name = NULL, *b_pmu_name = NULL;
        const char *a_name = "//", *a_desc = NULL, *a_topic = "";
        const char *b_name = "//", *b_desc = NULL, *b_topic = "";
        int ret;
@@ -1583,11 +1583,13 @@ static int cmp_sevent(const void *a, const void *b)
                a_name = as->event->name;
                a_desc = as->event->desc;
                a_topic = as->event->topic ?: "";
+               a_pmu_name = as->event->pmu_name;
        }
        if (bs->event) {
                b_name = bs->event->name;
                b_desc = bs->event->desc;
                b_topic = bs->event->topic ?: "";
+               b_pmu_name = bs->event->pmu_name;
        }
        /* Put extra events last. */
        if (!!a_desc != !!b_desc)
@@ -1603,11 +1605,13 @@ static int cmp_sevent(const void *a, const void *b)
                return as->is_cpu ? -1 : 1;
 
        /* Order by PMU name. */
-       a_pmu_name = as->pmu->name ?: "";
-       b_pmu_name = bs->pmu->name ?: "";
-       ret = strcmp(a_pmu_name, b_pmu_name);
-       if (ret)
-               return ret;
+       if (as->pmu != bs->pmu) {
+               a_pmu_name = a_pmu_name ?: (as->pmu->name ?: "");
+               b_pmu_name = b_pmu_name ?: (bs->pmu->name ?: "");
+               ret = strcmp(a_pmu_name, b_pmu_name);
+               if (ret)
+                       return ret;
+       }
 
        /* Order by event name. */
        return strcmp(a_name, b_name);
@@ -1621,17 +1625,26 @@ bool is_pmu_core(const char *name)
 static bool pmu_alias_is_duplicate(struct sevent *alias_a,
                                   struct sevent *alias_b)
 {
-       const char *a_pmu_name, *b_pmu_name;
-       const char *a_name = alias_a->event ? alias_a->event->name : "//";
-       const char *b_name = alias_b->event ? alias_b->event->name : "//";
+       const char *a_pmu_name = NULL, *b_pmu_name = NULL;
+       const char *a_name = "//", *b_name = "//";
+
+
+       if (alias_a->event) {
+               a_name = alias_a->event->name;
+               a_pmu_name = alias_a->event->pmu_name;
+       }
+       if (alias_b->event) {
+               b_name = alias_b->event->name;
+               b_pmu_name = alias_b->event->pmu_name;
+       }
 
        /* Different names -> never duplicates */
        if (strcmp(a_name, b_name))
                return false;
 
        /* Don't remove duplicates for different PMUs */
-       a_pmu_name = alias_a->pmu->name ?: "";
-       b_pmu_name = alias_b->pmu->name ?: "";
+       a_pmu_name = a_pmu_name ?: (alias_a->pmu->name ?: "");
+       b_pmu_name = b_pmu_name ?: (alias_b->pmu->name ?: "");
        return strcmp(a_pmu_name, b_pmu_name) == 0;
 }
 
@@ -1680,7 +1693,8 @@ void print_pmu_events(const struct print_callbacks *print_cb, void *print_state)
        for (j = 0; j < len; j++) {
                const char *name, *alias = NULL, *scale_unit = NULL,
                        *desc = NULL, *long_desc = NULL,
-                       *encoding_desc = NULL, *topic = NULL;
+                       *encoding_desc = NULL, *topic = NULL,
+                       *pmu_name = NULL;
                bool deprecated = false;
                size_t buf_used;
 
@@ -1690,7 +1704,8 @@ void print_pmu_events(const struct print_callbacks *print_cb, void *print_state)
 
                if (!aliases[j].event) {
                        /* A selectable event. */
-                       buf_used = snprintf(buf, sizeof(buf), "%s//", aliases[j].pmu->name) + 1;
+                       pmu_name = aliases[j].pmu->name;
+                       buf_used = snprintf(buf, sizeof(buf), "%s//", pmu_name) + 1;
                        name = buf;
                } else {
                        if (aliases[j].event->desc) {
@@ -1705,6 +1720,7 @@ void print_pmu_events(const struct print_callbacks *print_cb, void *print_state)
                                }
                                buf_used = strlen(buf) + 1;
                        }
+                       pmu_name = aliases[j].event->pmu_name ?: (aliases[j].pmu->name ?: "");
                        if (strlen(aliases[j].event->unit) || aliases[j].event->scale != 1.0) {
                                scale_unit = buf + buf_used;
                                buf_used += snprintf(buf + buf_used, sizeof(buf) - buf_used,
@@ -1716,12 +1732,11 @@ void print_pmu_events(const struct print_callbacks *print_cb, void *print_state)
                        topic = aliases[j].event->topic;
                        encoding_desc = buf + buf_used;
                        buf_used += snprintf(buf + buf_used, sizeof(buf) - buf_used,
-                                       "%s/%s/", aliases[j].pmu->name,
-                                       aliases[j].event->str) + 1;
+                                       "%s/%s/", pmu_name, aliases[j].event->str) + 1;
                        deprecated = aliases[j].event->deprecated;
                }
                print_cb->print_event(print_state,
-                               aliases[j].pmu->name,
+                               pmu_name,
                                topic,
                                name,
                                alias,