perf stat: Use counter cpumask to skip zero values
authorIan Rogers <irogers@google.com>
Thu, 3 Apr 2025 19:43:35 +0000 (12:43 -0700)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Mon, 12 May 2025 17:18:16 +0000 (14:18 -0300)
When a counter is 0 it may or may not be skipped.

For uncore counters it is common they are only valid on 1 logical CPU
and all other CPUs should be skipped.

The PMU's cpumask was used for the skip calculation, but that cpumask
may not reflect user overrides.

Similarly a counter on a core PMU may explicitly not request a CPU be
gathered.

If the counter on this CPU's value is 0 then the counter should be
skipped as it wasn't requested.

Switch from using the PMU cpumask to that associated with the evsel to
support these cases.

Avoid potential crash with --per-thread mode where config->aggr_get_id
is NULL. Add some examples for the tool event 0 counter skipping.

Signed-off-by: Ian Rogers <irogers@google.com>
Tested-by: Kan Liang <kan.liang@linux.intel.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Dominique Martinet <asmadeus@codewreck.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@linaro.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Leo Yan <leo.yan@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Weilin Wang <weilin.wang@intel.com>
Cc: Yicong Yang <yangyicong@hisilicon.com>
Link: https://lore.kernel.org/r/20250403194337.40202-3-irogers@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/stat-display.c

index aab3697aed63a8a1e17d1add7df8eaeda3249db7..e31d9f64d3aef5a36fe9bf7befa28dca08e82331 100644 (file)
@@ -1008,8 +1008,16 @@ static bool should_skip_zero_counter(struct perf_stat_config *config,
                return true;
 
        /*
-        * Many tool events are only gathered on the first index, skip other
-        * zero values.
+        * In per-thread mode the aggr_map and aggr_get_id functions may be
+        * NULL, assume all 0 values should be output in that case.
+        */
+       if (!config->aggr_map || !config->aggr_get_id)
+               return false;
+
+       /*
+        * Tool events may be gathered on all logical CPUs, for example
+        * system_time, but for many the first index is the only one used, for
+        * example num_cores. Don't skip for the first index.
         */
        if (evsel__is_tool(counter)) {
                struct aggr_cpu_id own_id =
@@ -1017,15 +1025,12 @@ static bool should_skip_zero_counter(struct perf_stat_config *config,
 
                return !aggr_cpu_id__equal(id, &own_id);
        }
-
        /*
-        * Skip value 0 when it's an uncore event and the given aggr id
-        * does not belong to the PMU cpumask.
+        * Skip value 0 when the counter's cpumask doesn't match the given aggr
+        * id.
         */
-       if (!counter->pmu || !counter->pmu->is_uncore)
-               return false;
 
-       perf_cpu_map__for_each_cpu(cpu, idx, counter->pmu->cpus) {
+       perf_cpu_map__for_each_cpu(cpu, idx, counter->core.cpus) {
                struct aggr_cpu_id own_id = config->aggr_get_id(config, cpu);
 
                if (aggr_cpu_id__equal(id, &own_id))