From: Michael Petlan <mpetlan@redhat.com>
To: linux-perf-users@vger.kernel.org, acme@redhat.com,
irogers@google.com, namhyung@kernel.org
Cc: jmario@redhat.com, jolsa@kernel.org
Subject: [PATCH 4/4] perf c2c report: Add --detect-shm option
Date: Mon, 6 Oct 2025 19:57:10 +0200 [thread overview]
Message-ID: <20251006175710.1179040-5-mpetlan@redhat.com> (raw)
In-Reply-To: <20251006175710.1179040-1-mpetlan@redhat.com>
Add an option that allows merging shared cachelines. In order to
better understand the problem, another column with physical memory
address is added to the Cacheline dimension.
Since the "PA Cnt" column contains obviously incorrect data, remove
it from Shared Data Cache Line Table to save space.
Suggested-by: Jiri Olsa <jolsa@kernel.org>
Suggested-by: Joe Mario <jmario@redhat.com>
Signed-off-by: Michael Petlan <mpetlan@redhat.com>
---
tools/perf/builtin-c2c.c | 102 +++++++++++++++++++++++++--------------
1 file changed, 66 insertions(+), 36 deletions(-)
diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c
index 78bcc18b7891..6f9a65528654 100644
--- a/tools/perf/builtin-c2c.c
+++ b/tools/perf/builtin-c2c.c
@@ -111,6 +111,7 @@ struct perf_c2c {
bool stats_only;
bool symbol_full;
bool stitch_lbr;
+ bool phys;
/* Shared cache line stats */
struct c2c_stats shared_clines_stats;
@@ -329,6 +330,13 @@ static int process_sample_event(const struct perf_tool *tool __maybe_unused,
goto out;
}
+ /* Keep only accesses to shared memory for --phys mode. */
+ if (c2c.phys && !map_is_shared_memory(mi->daddr.ms.map)) {
+ mem_info__put(mi);
+ ret = 0;
+ goto out;
+ }
+
/*
* The mi object is released in hists__add_entry_ops,
* if it gets sorted out into existing data, so we need
@@ -515,11 +523,20 @@ static int c2c_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
__s; \
})
+static int64_t
+sort__dcacheline_phys_cmp(struct hist_entry *left, struct hist_entry *right)
+{
+ return left->mem_info->daddr.phys_addr - right->mem_info->daddr.phys_addr;
+}
+
static int64_t
dcacheline_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
struct hist_entry *left, struct hist_entry *right)
{
- return sort__dcacheline_cmp(left, right);
+ if (c2c.phys)
+ return sort__dcacheline_phys_cmp(left, right);
+ else
+ return sort__dcacheline_cmp(left, right);
}
static int dcacheline_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
@@ -535,6 +552,20 @@ static int dcacheline_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
return scnprintf(hpp->buf, hpp->size, "%*s", width, HEX_STR(buf, addr));
}
+static int
+dcacheline_phys_addr_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+ struct hist_entry *he)
+{
+ uint64_t addr = 0;
+ int width = c2c_width(fmt, hpp, he->hists);
+ char buf[20];
+
+ if (he->mem_info)
+ addr = cl_address(mem_info__daddr(he->mem_info)->phys_addr, chk_double_cl);
+
+ return scnprintf(hpp->buf, hpp->size, "%*s", width, HEX_STR(buf, addr));
+}
+
static int
dcacheline_node_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
struct hist_entry *he)
@@ -1433,6 +1464,14 @@ static struct c2c_dimension dim_dcacheline = {
.width = 18,
};
+static struct c2c_dimension dim_dcacheline_phys_addr = {
+ .header = HEADER_LOW("Phys Address"),
+ .name = "dcacheline_phys_addr",
+ .cmp = empty_cmp,
+ .entry = dcacheline_phys_addr_entry,
+ .width = 18,
+};
+
static struct c2c_dimension dim_dcacheline_node = {
.header = HEADER_LOW("Node"),
.name = "dcacheline_node",
@@ -1888,6 +1927,7 @@ static struct c2c_dimension dim_dcacheline_map = {
static struct c2c_dimension *dimensions[] = {
&dim_dcacheline,
+ &dim_dcacheline_phys_addr,
&dim_dcacheline_node,
&dim_dcacheline_count,
&dim_offset,
@@ -2869,7 +2909,7 @@ static int ui_quirks(void)
buf = fill_line(chk_double_cl ? "Double-Cacheline" : "Cacheline",
dim_dcacheline.width +
dim_dcacheline_node.width +
- dim_dcacheline_count.width + 4);
+ (c2c.phys ? dim_dcacheline_phys_addr.width : dim_dcacheline_count.width) + 4);
if (!buf)
return -ENOMEM;
@@ -2878,6 +2918,7 @@ static int ui_quirks(void)
/* Fix the zero line for offset column. */
buf = fill_line(nodestr, dim_offset.width +
dim_offset_node.width +
+ (c2c.phys ? dim_dcacheline_phys_addr.width + 2 : 0) +
dim_dcacheline_count.width + 4);
if (!buf)
return -ENOMEM;
@@ -3004,7 +3045,7 @@ static int build_cl_output(char *cl_sort, bool no_source)
}
if (asprintf(&c2c.cl_output,
- "%s%s%s%s%s%s%s%s%s%s%s%s",
+ "%s%s%s%s%s%s%s%s%s%s%s%s%s",
c2c.use_stdio ? "cl_num_empty," : "",
c2c.display == DISPLAY_SNP_PEER ? "percent_rmt_peer,"
"percent_lcl_peer," :
@@ -3014,6 +3055,7 @@ static int build_cl_output(char *cl_sort, bool no_source)
"percent_stores_l1miss,"
"percent_stores_na,"
"offset,offset_node,dcacheline_count,",
+ c2c.phys ? "dcacheline_phys_addr," : "",
add_pid ? "pid," : "",
add_tid ? "tid," : "",
add_iaddr ? "iaddr," : "",
@@ -3100,6 +3142,7 @@ static int perf_c2c__report(int argc, const char **argv)
"Do not display Source Line column"),
OPT_BOOLEAN(0, "show-all", &c2c.show_all,
"Show all captured HITM lines."),
+ OPT_BOOLEAN(0, "detect-shm", &c2c.phys, "Merge shared cachelines"),
OPT_CALLBACK_DEFAULT('g', "call-graph", &callchain_param,
"print_type,threshold[,print_limit],order,sort_key[,branch],value",
callchain_help, &parse_callchain_opt,
@@ -3115,7 +3158,8 @@ static int perf_c2c__report(int argc, const char **argv)
OPT_END()
};
int err = 0;
- const char *output_str, *sort_str = NULL;
+ char *output_str;
+ const char *sort_str = NULL;
struct perf_env *env;
argc = parse_options(argc, argv, options, report_c2c_usage,
@@ -3226,38 +3270,22 @@ static int perf_c2c__report(int argc, const char **argv)
goto out_mem2node;
}
- if (c2c.display != DISPLAY_SNP_PEER)
- output_str = "cl_idx,"
- "cl_shared,"
- "dcacheline,"
- "dcacheline_node,"
- "dcacheline_count,"
- "percent_costly_snoop,"
- "tot_hitm,lcl_hitm,rmt_hitm,"
- "tot_recs,"
- "tot_loads,"
- "tot_stores,"
- "stores_l1hit,stores_l1miss,stores_na,"
- "ld_fbhit,ld_l1hit,ld_l2hit,"
- "ld_lclhit,lcl_hitm,"
- "ld_rmthit,rmt_hitm,"
- "dram_lcl,dram_rmt,cl_map";
- else
- output_str = "cl_idx,"
- "cl_shared,"
- "dcacheline,"
- "dcacheline_node,"
- "dcacheline_count,"
- "percent_costly_snoop,"
- "tot_peer,lcl_peer,rmt_peer,"
- "tot_recs,"
- "tot_loads,"
- "tot_stores,"
- "stores_l1hit,stores_l1miss,stores_na,"
- "ld_fbhit,ld_l1hit,ld_l2hit,"
- "ld_lclhit,lcl_hitm,"
- "ld_rmthit,rmt_hitm,"
- "dram_lcl,dram_rmt,cl_map";
+ if (asprintf(&output_str, "%s%s%s%s%s",
+ "cl_idx,"
+ "cl_shared,"
+ "dcacheline,",
+ c2c.phys ? "dcacheline_phys_addr,dcacheline_node," : "dcacheline_node,dcacheline_count,",
+ "percent_costly_snoop,",
+ (c2c.display == DISPLAY_SNP_PEER) ? "tot_peer,lcl_peer,rmt_peer," : "tot_hitm,lcl_hitm,rmt_hitm,",
+ "tot_recs,"
+ "tot_loads,"
+ "tot_stores,"
+ "stores_l1hit,stores_l1miss,stores_na,"
+ "ld_fbhit,ld_l1hit,ld_l2hit,"
+ "ld_lclhit,lcl_hitm,"
+ "ld_rmthit,rmt_hitm,"
+ "dram_lcl,dram_rmt,cl_map") < 0)
+ goto out_mem2node;
if (c2c.display == DISPLAY_TOT_HITM)
sort_str = "tot_hitm";
@@ -3270,6 +3298,8 @@ static int perf_c2c__report(int argc, const char **argv)
c2c_hists__reinit(&c2c.hists, output_str, sort_str, perf_session__env(session));
+ free(output_str);
+
ui_progress__init(&prog, c2c.hists.hists.nr_entries, "Sorting...");
hists__collapse_resort(&c2c.hists.hists, NULL);
--
2.47.3
next prev parent reply other threads:[~2025-10-06 17:57 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-10-06 17:57 [PATCH 0/4] perf c2c: Detect shared memory cachelines Michael Petlan
2025-10-06 17:57 ` [PATCH 1/4] perf tools: Remove /SYSV from no_dso maps Michael Petlan
2025-10-06 18:01 ` Ian Rogers
2025-10-06 18:28 ` Joe Mario
2025-10-06 19:21 ` Ian Rogers
2025-10-06 17:57 ` [PATCH 2/4] perf c2c: Add shared mem flag Michael Petlan
2025-10-06 17:57 ` [PATCH 3/4] perf c2c: Add map name for cacheline Michael Petlan
2025-10-06 17:57 ` Michael Petlan [this message]
2025-10-07 8:16 ` [PATCH 0/4] perf c2c: Detect shared memory cachelines Namhyung Kim
2025-10-07 14:38 ` Arnaldo Carvalho de Melo
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=20251006175710.1179040-5-mpetlan@redhat.com \
--to=mpetlan@redhat.com \
--cc=acme@redhat.com \
--cc=irogers@google.com \
--cc=jmario@redhat.com \
--cc=jolsa@kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=namhyung@kernel.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;
as well as URLs for NNTP newsgroup(s).