]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
perf stat: Sort default events/metrics
authorIan Rogers <irogers@google.com>
Tue, 11 Nov 2025 21:21:57 +0000 (13:21 -0800)
committerNamhyung Kim <namhyung@kernel.org>
Wed, 12 Nov 2025 00:48:35 +0000 (16:48 -0800)
To improve the readability of default events/metrics, sort the evsels
after the Default metric groups have be parsed.

Before:
```
$ perf stat -a sleep 1
 Performance counter stats for 'system wide':

            22,087      context-switches                 #      nan cs/sec  cs_per_second
             TopdownL1 (cpu_core)                 #     10.3 %  tma_bad_speculation
                                                  #     25.8 %  tma_frontend_bound
                                                  #     34.5 %  tma_backend_bound
                                                  #     29.3 %  tma_retiring
             7,829      page-faults                      #      nan faults/sec  page_faults_per_second
       880,144,270      cpu_atom/cpu-cycles/             #      nan GHz  cycles_frequency       (50.10%)
     1,693,081,235      cpu_core/cpu-cycles/             #      nan GHz  cycles_frequency
             TopdownL1 (cpu_atom)                 #     20.5 %  tma_bad_speculation
                                                  #     13.8 %  tma_retiring             (50.26%)
                                                  #     34.6 %  tma_frontend_bound       (50.23%)
        89,326,916      cpu_atom/branches/               #      nan M/sec  branch_frequency     (60.19%)
       538,123,088      cpu_core/branches/               #      nan M/sec  branch_frequency
             1,368      cpu-migrations                   #      nan migrations/sec  migrations_per_second
                                                  #     31.1 %  tma_backend_bound        (60.19%)
              0.00 msec cpu-clock                        #      0.0 CPUs  CPUs_utilized
       485,744,856      cpu_atom/instructions/           #      0.6 instructions  insn_per_cycle  (59.87%)
     3,093,112,283      cpu_core/instructions/           #      1.8 instructions  insn_per_cycle
         4,939,427      cpu_atom/branch-misses/          #      5.0 %  branch_miss_rate         (49.77%)
         7,632,248      cpu_core/branch-misses/          #      1.4 %  branch_miss_rate

       1.005084693 seconds time elapsed
```
After:
```
$ perf stat -a sleep 1
 Performance counter stats for 'system wide':

            22,165      context-switches                 #      nan cs/sec  cs_per_second
              0.00 msec cpu-clock                        #      0.0 CPUs  CPUs_utilized
             2,260      cpu-migrations                   #      nan migrations/sec  migrations_per_second
            20,476      page-faults                      #      nan faults/sec  page_faults_per_second
        17,052,357      cpu_core/branch-misses/          #      1.5 %  branch_miss_rate
     1,120,090,590      cpu_core/branches/               #      nan M/sec  branch_frequency
     3,402,892,275      cpu_core/cpu-cycles/             #      nan GHz  cycles_frequency
     6,129,236,701      cpu_core/instructions/           #      1.8 instructions  insn_per_cycle
         6,159,523      cpu_atom/branch-misses/          #      3.1 %  branch_miss_rate         (49.86%)
       222,158,812      cpu_atom/branches/               #      nan M/sec  branch_frequency     (50.25%)
     1,547,610,244      cpu_atom/cpu-cycles/             #      nan GHz  cycles_frequency       (50.40%)
     1,304,901,260      cpu_atom/instructions/           #      0.8 instructions  insn_per_cycle  (50.41%)
             TopdownL1 (cpu_core)                 #     13.7 %  tma_bad_speculation
                                                  #     23.5 %  tma_frontend_bound
                                                  #     33.3 %  tma_backend_bound
                                                  #     29.6 %  tma_retiring
             TopdownL1 (cpu_atom)                 #     32.1 %  tma_backend_bound        (59.65%)
                                                  #     30.1 %  tma_frontend_bound       (59.51%)
                                                  #     22.3 %  tma_bad_speculation
                                                  #     15.5 %  tma_retiring             (59.53%)

       1.008405429 seconds time elapsed
```

Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
tools/perf/builtin-stat.c

index 7862094b93c88f19c079682ccf880cba47470a1f..095016b2209e92f4ed6b47b1b9ea2e080c74c1ce 100644 (file)
@@ -74,6 +74,7 @@
 #include "util/intel-tpebs.h"
 #include "asm/bug.h"
 
+#include <linux/list_sort.h>
 #include <linux/time64.h>
 #include <linux/zalloc.h>
 #include <api/fs/fs.h>
@@ -1857,6 +1858,35 @@ static int perf_stat_init_aggr_mode_file(struct perf_stat *st)
        return 0;
 }
 
+static int default_evlist_evsel_cmp(void *priv __maybe_unused,
+                                   const struct list_head *l,
+                                   const struct list_head *r)
+{
+       const struct perf_evsel *lhs_core = container_of(l, struct perf_evsel, node);
+       const struct evsel *lhs = container_of(lhs_core, struct evsel, core);
+       const struct perf_evsel *rhs_core = container_of(r, struct perf_evsel, node);
+       const struct evsel *rhs = container_of(rhs_core, struct evsel, core);
+
+       if (evsel__leader(lhs) == evsel__leader(rhs)) {
+               /* Within the same group, respect the original order. */
+               return lhs_core->idx - rhs_core->idx;
+       }
+
+       /* Sort default metrics evsels first, and default show events before those. */
+       if (lhs->default_metricgroup != rhs->default_metricgroup)
+               return lhs->default_metricgroup ? -1 : 1;
+
+       if (lhs->default_show_events != rhs->default_show_events)
+               return lhs->default_show_events ? -1 : 1;
+
+       /* Sort by PMU type (prefers legacy types first). */
+       if (lhs->pmu != rhs->pmu)
+               return lhs->pmu->type - rhs->pmu->type;
+
+       /* Sort by name. */
+       return strcmp(evsel__name((struct evsel *)lhs), evsel__name((struct evsel *)rhs));
+}
+
 /*
  * Add default events, if there were no attributes specified or
  * if -d/--detailed, -d -d or -d -d -d is used:
@@ -2023,6 +2053,8 @@ static int add_default_events(void)
                                                        &metric_evlist->metric_events);
                        evlist__delete(metric_evlist);
                }
+               list_sort(/*priv=*/NULL, &evlist->core.entries, default_evlist_evsel_cmp);
+
        }
 out:
        if (!ret) {