[PATCH 11/12] perf mem record: Request PERF_SAMPLE_CPU by default

From: Arnaldo Carvalho de Melo

Date: Wed Sep 16 2026 - 15:13:14 EST


From: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>

The data-type profiling per-sample stream keys cross-CPU contention on
sample->cpu: without PERF_SAMPLE_CPU the cpu field is the (u32)-1 "no
CPU info" sentinel, documented as such in perf_session__deliver_event(),
and same-instance reads and writes from different cores are
indistinguishable from same-CPU traffic, so pahole's false-sharing
detector cannot tell them apart.

builtin-record.c already defines --sample-cpu and 'perf mem record'
forwards unknown options to the record parser, so passing it explicitly
works today; make it the default, next to the -d (addr) and -W (weight)
the command already requests, documenting it in perf-mem(1).

The rec_argv array is sized as nine arguments per memory PMU plus the
user arguments, not counting the arguments __cmd_record() adds itself,
up to eight with all the optional flags. On PMUs with separate load and
store events the four event arguments plus the fixed ones already filled
the array to its last slot, so this new argument would write past it;
reserve space for the fixed arguments explicitly.

Assisted-by: LLM
Signed-off-by: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>
---
tools/perf/Documentation/perf-mem.txt | 4 ++++
tools/perf/builtin-mem.c | 18 ++++++++++++++++--
2 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/tools/perf/Documentation/perf-mem.txt b/tools/perf/Documentation/perf-mem.txt
index 4d164836d0943119..fe51c5e3333dc4a0 100644
--- a/tools/perf/Documentation/perf-mem.txt
+++ b/tools/perf/Documentation/perf-mem.txt
@@ -14,6 +14,10 @@ DESCRIPTION
-----------
"perf mem record" runs a command and gathers memory operation data
from it, into perf.data. Perf record options are accepted and are passed through.
+It also requests the address (-d), the weight (-W, where supported) and the
+CPU id (--sample-cpu) of every sampled access by default; the CPU id is what
+lets per-sample analysis tell reads and writes to the same data from
+different cores apart from same-CPU traffic.

"perf mem report" displays the result. It invokes perf report with the
right set of options to display a memory access profile. By default, loads
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index 6101a26b3a781e69..6f38cda1a45ada16 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -99,8 +99,13 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem,
argc = parse_options(argc, argv, options, record_usage,
PARSE_OPT_KEEP_UNKNOWN);

- /* Max number of arguments multiplied by number of PMUs that can support them. */
- rec_argc = argc + 9 * (perf_pmu__mem_events_num_mem_pmus(pmu) + 1);
+ /*
+ * Max number of arguments multiplied by number of PMUs that can
+ * support them, plus the arguments added directly below, at most:
+ * "record", "-W", "-d", "--sample-cpu", "--phys-data",
+ * "--data-page-size", "--all-user" and "--all-kernel".
+ */
+ rec_argc = argc + 8 + 9 * (perf_pmu__mem_events_num_mem_pmus(pmu) + 1);

if (mem->cpu_list)
rec_argc += 2;
@@ -135,6 +140,15 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem,

rec_argv[i++] = "-d";

+ /*
+ * The data-type profiling per-sample stream keys cross-CPU
+ * contention on sample->cpu (PERF_SAMPLE_CPU); without it the cpu
+ * field is the (u32)-1 'no CPU info' sentinel and same-instance
+ * reads and writes from different cores are indistinguishable
+ * from same-CPU traffic.
+ */
+ rec_argv[i++] = "--sample-cpu";
+
if (mem->phys_addr)
rec_argv[i++] = "--phys-data";

--
2.55.0