From: Ian Rogers <irogers@google.com>
To: Peter Zijlstra <peterz@infradead.org>,
Ingo Molnar <mingo@redhat.com>,
Arnaldo Carvalho de Melo <acme@kernel.org>,
Namhyung Kim <namhyung@kernel.org>, Jiri Olsa <jolsa@kernel.org>,
Ian Rogers <irogers@google.com>,
Adrian Hunter <adrian.hunter@intel.com>,
James Clark <james.clark@linaro.org>
Cc: linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH v2 24/30] perf stat: Share events between metrics and command line events
Date: Fri, 13 Nov 2026 11:53:29 -0800 [thread overview]
Message-ID: <20261113195335.2865725-25-irogers@google.com> (raw)
In-Reply-To: <20261113195335.2865725-1-irogers@google.com>
The metrics added by -T, --smi-cost, --topdown and the Default metric
groups were parsed into a separate evlist and then added to the events
from the command line, so they didn't share events with them or, for
the Default metric groups, with each other.
Parse them directly into evsel_list so that the evsel matcher of
metricgroup__parse_groups() shares events counting the same thing. Only
mark the newly added events as skippable and keep the evsel indices in
list order after sorting the Default metric events, as required when
writing the group descriptions of a perf.data file. This removes the
copying of the metric events from the separate evlist with
metricgroup__copy_metric_events(), which crashed for "perf stat -T" on
an Alder Lake system.
For example, "perf stat -e duration_time -T" now uses the duration_time
event from the command line for the transaction metrics.
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/builtin-stat.c | 72 +++++++++++++++++++++++----------------
1 file changed, 43 insertions(+), 29 deletions(-)
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index f81192cec481..2b563382cf43 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1975,6 +1975,15 @@ static int default_evlist_evsel_cmp(void *priv __maybe_unused,
evsel__name((struct evsel *)rhs_leader));
}
+static bool evsel_in_array(const struct evsel *evsel, struct evsel * const *evsels, int nr)
+{
+ for (int i = 0; i < nr; i++) {
+ if (evsels[i] == evsel)
+ return true;
+ }
+ return false;
+}
+
/*
* Add default events, if there were no attributes specified or
* if -d/--detailed, -d -d or -d -d -d is used:
@@ -1984,18 +1993,31 @@ static int add_default_events(void)
const char *pmu = parse_events_option_args.pmu_filter ?: "all";
struct perf_pmus *pmus = perf_env__pmus(host_env());
struct parse_events_error err;
- struct evlist *evlist = evlist__new();
+ /*
+ * Add the metrics directly to evsel_list so that they share events
+ * with the events and metrics already there.
+ */
+ struct evlist *evlist = evsel_list;
+ int nr_orig_entries = evlist__nr_entries(evlist);
+ struct evsel **orig_evsels = NULL;
struct evsel *evsel;
- int ret = 0;
+ int idx = 0, ret = 0;
- if (!evlist)
- return -ENOMEM;
+ /* Set attrs if no event is selected and !null_run: */
+ if (stat_config.null_run)
+ return 0;
parse_events_error__init(&err);
- /* Set attrs if no event is selected and !null_run: */
- if (stat_config.null_run)
- goto out;
+ if (nr_orig_entries > 0) {
+ orig_evsels = calloc(nr_orig_entries, sizeof(*orig_evsels));
+ if (!orig_evsels) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ evlist__for_each_entry(evlist, evsel)
+ orig_evsels[idx++] = evsel;
+ }
if (transaction_run) {
/* Handle -T as -M transaction. Once platform specific metrics
@@ -2101,7 +2123,7 @@ static int add_default_events(void)
if (!stat_config.topdown_level)
stat_config.topdown_level = 1;
- if (!evlist__nr_entries(evlist) && !evlist__nr_entries(evsel_list)) {
+ if (!evlist__nr_entries(evlist)) {
/*
* Add Default metrics. To minimize multiplexing, don't request
* threshold computation, but it will be computed if the events
@@ -2112,8 +2134,6 @@ static int add_default_events(void)
};
for (size_t i = 0; i < ARRAY_SIZE(default_metricgroup_names); i++) {
- struct evlist *metric_evlist;
-
if (!metricgroup__has_metric_or_groups(pmus, pmu,
default_metricgroup_names[i]))
continue;
@@ -2121,12 +2141,7 @@ static int add_default_events(void)
if ((int)i > detailed_run)
break;
- metric_evlist = evlist__new();
- if (!metric_evlist) {
- ret = -ENOMEM;
- break;
- }
- if (metricgroup__parse_groups(metric_evlist, pmu,
+ if (metricgroup__parse_groups(evlist, pmu,
parse_events_option_args.cputype_filter,
default_metricgroup_names[i],
/*metric_no_group=*/false,
@@ -2135,26 +2150,29 @@ static int add_default_events(void)
stat_config.user_requested_cpu_list,
stat_config.system_wide,
stat_config.hardware_aware_grouping) < 0) {
- evlist__put(metric_evlist);
ret = -1;
break;
}
- evlist__for_each_entry(metric_evlist, evsel)
+ /* evsel_list was empty so all the events are for the Default metrics. */
+ evlist__for_each_entry(evlist, evsel)
evsel->default_metricgroup = true;
-
- evlist__splice_list_tail(evlist, &evlist__core(metric_evlist)->entries);
- metricgroup__copy_metric_events(evlist, /*cgrp=*/NULL,
- evlist__metric_events(evlist),
- evlist__metric_events(metric_evlist));
- evlist__put(metric_evlist);
}
list_sort(/*priv=*/NULL, &evlist__core(evlist)->entries, default_evlist_evsel_cmp);
+ /* Keep the indices in list order, as required by the perf.data header. */
+ idx = 0;
+ evlist__for_each_entry(evlist, evsel) {
+ evsel->core.idx = idx++;
+ evsel->tracking = !evsel->core.idx;
+ }
}
out:
if (!ret) {
evlist__for_each_entry(evlist, evsel) {
+ /* Only events added here, not those from the command line. */
+ if (evsel_in_array(evsel, orig_evsels, nr_orig_entries))
+ continue;
/*
* Make at least one event non-skippable so fatal errors are visible.
* 'cycles' always used to be default and non-skippable, so use that.
@@ -2163,12 +2181,8 @@ static int add_default_events(void)
evsel->skippable = true;
}
}
+ free(orig_evsels);
parse_events_error__exit(&err);
- evlist__splice_list_tail(evsel_list, &evlist__core(evlist)->entries);
- metricgroup__copy_metric_events(evsel_list, /*cgrp=*/NULL,
- evlist__metric_events(evsel_list),
- evlist__metric_events(evlist));
- evlist__put(evlist);
return ret;
}
--
2.56.1.703.gf848ed807c-goog
next prev parent reply other threads:[~2026-11-13 19:54 UTC|newest]
Thread overview: 61+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-13 19:53 [PATCH v2 00/30] perf: Per-env PMUs, metric event sharing, and recorded event metrics Ian Rogers
2026-11-13 19:53 ` [PATCH v2 01/30] perf pmus: Don't skip core PMUs as duplicates Ian Rogers
2026-11-13 20:04 ` sashiko-bot
2026-11-13 19:53 ` [PATCH v2 02/30] perf script: Fix metrics computed from samples Ian Rogers
2026-11-13 20:05 ` sashiko-bot
2026-11-13 19:53 ` [PATCH v2 03/30] perf script: Don't drop metric samples for CPUs missing from the evsel Ian Rogers
2026-11-13 20:02 ` sashiko-bot
2026-11-13 19:53 ` [PATCH v2 04/30] perf metricgroup: Don't prefer tool events for displaying a metric Ian Rogers
2026-11-13 19:59 ` sashiko-bot
2026-11-13 19:53 ` [PATCH v2 05/30] perf env: Make lazy perf_env initialization thread-safe Ian Rogers
2026-11-13 20:05 ` sashiko-bot
2026-11-13 19:53 ` [PATCH v2 06/30] perf env: Add host_env() singleton Ian Rogers
2026-11-13 20:47 ` sashiko-bot
2026-11-13 19:53 ` [PATCH v2 07/30] perf pmu: Add from_env parameter to perf_pmu__init() Ian Rogers
2026-11-13 20:10 ` sashiko-bot
2026-11-13 19:53 ` [PATCH v2 08/30] perf pmus: Introduce struct perf_pmus and perf_env__pmus() Ian Rogers
2026-11-13 20:36 ` sashiko-bot
2026-11-13 19:53 ` [PATCH v2 09/30] perf pmus: Pass struct perf_pmus to find helpers Ian Rogers
2026-11-13 20:11 ` sashiko-bot
2026-11-13 19:53 ` [PATCH v2 10/30] perf pmus: Pass struct perf_pmus to scan helpers Ian Rogers
2026-11-13 20:06 ` sashiko-bot
2026-11-13 19:53 ` [PATCH v2 11/30] perf pmu-events: Add e_machine to struct pmu_events_map Ian Rogers
2026-11-13 20:12 ` sashiko-bot
2026-11-13 19:53 ` [PATCH v2 12/30] perf pmu-events: Pass e_machine to find_core_*_table() Ian Rogers
2026-11-13 20:05 ` sashiko-bot
2026-11-13 19:53 ` [PATCH v2 13/30] perf header: Pass e_machine to strcmp_cpuid_str() Ian Rogers
2026-11-13 20:01 ` sashiko-bot
2026-11-13 19:53 ` [PATCH v2 14/30] perf header: Support CPUID matching across all architectures Ian Rogers
2026-11-13 20:05 ` sashiko-bot
2026-11-13 19:53 ` [PATCH v2 15/30] perf test: Make the CPUID matching test architecture independent Ian Rogers
2026-11-13 20:02 ` sashiko-bot
2026-11-13 19:53 ` [PATCH v2 16/30] perf test: Add CPUID matching tests for other architectures Ian Rogers
2026-11-13 20:03 ` sashiko-bot
2026-11-13 19:53 ` [PATCH v2 17/30] perf dwarf-regs: Add e_machine__same_arch() Ian Rogers
2026-11-13 20:00 ` sashiko-bot
2026-11-13 19:53 ` [PATCH v2 18/30] perf metricgroup: Pass struct perf_pmus to metricgroup__for_each_metric() Ian Rogers
2026-11-13 20:37 ` sashiko-bot
2026-11-13 19:53 ` [PATCH v2 19/30] perf metricgroup: Move matching of metrics to recorded events from perf script Ian Rogers
2026-11-13 20:59 ` sashiko-bot
2026-11-13 19:53 ` [PATCH v2 20/30] perf parse-events: Decode metric-id terms when adding events Ian Rogers
2026-11-13 20:33 ` sashiko-bot
2026-11-13 19:53 ` [PATCH v2 21/30] perf evsel: Generalize metric_id to a set of metric_ids Ian Rogers
2026-11-13 20:31 ` sashiko-bot
2026-11-13 19:53 ` [PATCH v2 22/30] perf pmu: Add perf_pmu__for_each_name_from_config() Ian Rogers
2026-11-13 20:13 ` sashiko-bot
2026-11-13 19:53 ` [PATCH v2 23/30] perf metricgroup: Share metric events by their counter encoding Ian Rogers
2026-11-13 20:59 ` sashiko-bot
2026-11-13 19:53 ` Ian Rogers [this message]
2026-11-13 20:14 ` [PATCH v2 24/30] perf stat: Share events between metrics and command line events sashiko-bot
2026-11-13 19:53 ` [PATCH v2 25/30] perf pmus: Add perf_pmus__read_from_env() Ian Rogers
2026-11-13 21:05 ` sashiko-bot
2026-11-13 19:53 ` [PATCH v2 26/30] perf metricgroup: Improve matching of metrics to recorded events Ian Rogers
2026-11-13 20:37 ` sashiko-bot
2026-11-13 19:53 ` [PATCH v2 27/30] perf metricgroup: Add metricgroup__add_recorded_metrics() Ian Rogers
2026-11-13 20:42 ` sashiko-bot
2026-11-13 19:53 ` [PATCH v2 28/30] perf stat report: Display metrics for recorded events Ian Rogers
2026-11-13 20:44 ` sashiko-bot
2026-11-13 19:53 ` [PATCH v2 29/30] perf script: Display metrics for perf stat record data Ian Rogers
2026-11-13 20:47 ` sashiko-bot
2026-11-13 19:53 ` [PATCH v2 30/30] perf test: Add stat record metrics test Ian Rogers
2026-11-13 20:14 ` sashiko-bot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261113195335.2865725-25-irogers@google.com \
--to=irogers@google.com \
--cc=acme@kernel.org \
--cc=adrian.hunter@intel.com \
--cc=james.clark@linaro.org \
--cc=jolsa@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=namhyung@kernel.org \
--cc=peterz@infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox