Skip to content

Commit cd3466c

Browse files
TianyouLinamhyung
authored andcommitted
perf c2c: Add annotation support to perf c2c report
Perf c2c report currently specified the code address and source:line information in the cacheline browser, while it is lack of annotation support like perf report to directly show the disassembly code for the particular symbol shared that same cacheline. This patches add a key 'a' binding to the cacheline browser which reuse the annotation browser to show the disassembly view for easier analysis of cacheline contentions. Signed-off-by: Tianyou Li <tianyou.li@intel.com> Reviewed-by: Dapeng Mi <dapeng1.mi@linux.intel.com> Reviewed-by: Thomas Falcon <thomas.falcon@intel.com> Reviewed-by: Jiebin Sun <jiebin.sun@intel.com> Reviewed-by: Pan Deng <pan.deng@intel.com> Reviewed-by: Zhiguo Zhou <zhiguo.zhou@intel.com> Reviewed-by: Wangyang Guo <wangyang.guo@intel.com> Tested-by: Ravi Bangoria <ravi.bangoria@amd.com> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
1 parent b830851 commit cd3466c

File tree

2 files changed

+157
-5
lines changed

2 files changed

+157
-5
lines changed

tools/perf/Documentation/perf-c2c.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,13 @@ REPORT OPTIONS
143143
feature, which causes cacheline sharing to behave like the cacheline
144144
size is doubled.
145145

146+
-M::
147+
--disassembler-style=::
148+
Set disassembler style for objdump.
149+
150+
--objdump=<path>::
151+
Path to objdump binary.
152+
146153
C2C RECORD
147154
----------
148155
The perf c2c record command setup options related to HITM cacheline analysis

tools/perf/builtin-c2c.c

Lines changed: 150 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545
#include "pmus.h"
4646
#include "string2.h"
4747
#include "util/util.h"
48+
#include "util/symbol.h"
49+
#include "util/annotate.h"
4850

4951
struct c2c_hists {
5052
struct hists hists;
@@ -62,6 +64,7 @@ struct compute_stats {
6264

6365
struct c2c_hist_entry {
6466
struct c2c_hists *hists;
67+
struct evsel *evsel;
6568
struct c2c_stats stats;
6669
unsigned long *cpuset;
6770
unsigned long *nodeset;
@@ -225,6 +228,12 @@ he__get_c2c_hists(struct hist_entry *he,
225228
return hists;
226229
}
227230

231+
static void c2c_he__set_evsel(struct c2c_hist_entry *c2c_he,
232+
struct evsel *evsel)
233+
{
234+
c2c_he->evsel = evsel;
235+
}
236+
228237
static void c2c_he__set_cpu(struct c2c_hist_entry *c2c_he,
229238
struct perf_sample *sample)
230239
{
@@ -275,6 +284,33 @@ static void compute_stats(struct c2c_hist_entry *c2c_he,
275284
update_stats(&cstats->load, weight);
276285
}
277286

287+
/*
288+
* Return true if annotation is possible. When list is NULL,
289+
* it means that we are called at the c2c_browser level,
290+
* in that case we allow annotation to be initialized. When list
291+
* is non-NULL, it means that we are called at the cacheline_browser
292+
* level, in that case we allow annotation only if use_browser
293+
* is set and symbol information is available.
294+
*/
295+
static bool perf_c2c__has_annotation(struct perf_hpp_list *list)
296+
{
297+
if (use_browser != 1)
298+
return false;
299+
return !list || list->sym;
300+
}
301+
302+
static void perf_c2c__evsel_hists_inc_stats(struct evsel *evsel,
303+
struct hist_entry *he,
304+
struct perf_sample *sample)
305+
{
306+
struct hists *evsel_hists = evsel__hists(evsel);
307+
308+
hists__inc_nr_samples(evsel_hists, he->filtered);
309+
evsel_hists->stats.total_period += sample->period;
310+
if (!he->filtered)
311+
evsel_hists->stats.total_non_filtered_period += sample->period;
312+
}
313+
278314
static int process_sample_event(const struct perf_tool *tool __maybe_unused,
279315
union perf_event *event,
280316
struct perf_sample *sample,
@@ -334,8 +370,15 @@ static int process_sample_event(const struct perf_tool *tool __maybe_unused,
334370

335371
c2c_he__set_cpu(c2c_he, sample);
336372
c2c_he__set_node(c2c_he, sample);
373+
c2c_he__set_evsel(c2c_he, evsel);
337374

338375
hists__inc_nr_samples(&c2c_hists->hists, he->filtered);
376+
377+
if (perf_c2c__has_annotation(NULL)) {
378+
perf_c2c__evsel_hists_inc_stats(evsel, he, sample);
379+
addr_map_symbol__inc_samples(mem_info__iaddr(mi), sample, evsel);
380+
}
381+
339382
ret = hist_entry__append_callchain(he, sample);
340383

341384
if (!ret) {
@@ -371,6 +414,7 @@ static int process_sample_event(const struct perf_tool *tool __maybe_unused,
371414

372415
c2c_he__set_cpu(c2c_he, sample);
373416
c2c_he__set_node(c2c_he, sample);
417+
c2c_he__set_evsel(c2c_he, evsel);
374418

375419
hists__inc_nr_samples(&c2c_hists->hists, he->filtered);
376420
ret = hist_entry__append_callchain(he, sample);
@@ -1997,6 +2041,9 @@ static int c2c_hists__init_sort(struct perf_hpp_list *hpp_list, char *name, stru
19972041
if (dim == &dim_dso)
19982042
hpp_list->dso = 1;
19992043

2044+
if (dim == &dim_symbol || dim == &dim_iaddr)
2045+
hpp_list->sym = 1;
2046+
20002047
perf_hpp_list__register_sort_field(hpp_list, &c2c_fmt->fmt);
20012048
return 0;
20022049
}
@@ -2550,6 +2597,40 @@ static void perf_c2c__hists_fprintf(FILE *out, struct perf_session *session)
25502597
}
25512598

25522599
#ifdef HAVE_SLANG_SUPPORT
2600+
2601+
static int perf_c2c__toggle_annotation(struct hist_browser *browser)
2602+
{
2603+
struct hist_entry *he = browser->he_selection;
2604+
struct symbol *sym = NULL;
2605+
struct annotated_source *src = NULL;
2606+
struct c2c_hist_entry *c2c_he = NULL;
2607+
2608+
if (!perf_c2c__has_annotation(he->hists->hpp_list)) {
2609+
ui_browser__help_window(&browser->b, "No annotation support");
2610+
return 0;
2611+
}
2612+
2613+
if (he == NULL) {
2614+
ui_browser__help_window(&browser->b, "No entry selected for annotation");
2615+
return 0;
2616+
}
2617+
2618+
sym = he->ms.sym;
2619+
if (sym == NULL) {
2620+
ui_browser__help_window(&browser->b, "Can not annotate, no symbol found");
2621+
return 0;
2622+
}
2623+
2624+
src = symbol__hists(sym, 0);
2625+
if (src == NULL) {
2626+
ui_browser__help_window(&browser->b, "Failed to initialize annotation source");
2627+
return 0;
2628+
}
2629+
2630+
c2c_he = container_of(he, struct c2c_hist_entry, he);
2631+
return hist_entry__tui_annotate(he, c2c_he->evsel, NULL);
2632+
}
2633+
25532634
static void c2c_browser__update_nr_entries(struct hist_browser *hb)
25542635
{
25552636
u64 nr_entries = 0;
@@ -2617,6 +2698,7 @@ static int perf_c2c__browse_cacheline(struct hist_entry *he)
26172698
" ENTER Toggle callchains (if present) \n"
26182699
" n Toggle Node details info \n"
26192700
" s Toggle full length of symbol and source line columns \n"
2701+
" a Toggle annotation view \n"
26202702
" q Return back to cacheline list \n";
26212703

26222704
if (!he)
@@ -2651,6 +2733,9 @@ static int perf_c2c__browse_cacheline(struct hist_entry *he)
26512733
c2c.node_info = (c2c.node_info + 1) % 3;
26522734
setup_nodes_header();
26532735
break;
2736+
case 'a':
2737+
perf_c2c__toggle_annotation(browser);
2738+
break;
26542739
case 'q':
26552740
goto out;
26562741
case '?':
@@ -3006,6 +3091,7 @@ static int perf_c2c__report(int argc, const char **argv)
30063091
const char *display = NULL;
30073092
const char *coalesce = NULL;
30083093
bool no_source = false;
3094+
const char *disassembler_style = NULL, *objdump_path = NULL;
30093095
const struct option options[] = {
30103096
OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
30113097
"file", "vmlinux pathname"),
@@ -3033,13 +3119,23 @@ static int perf_c2c__report(int argc, const char **argv)
30333119
OPT_BOOLEAN(0, "stitch-lbr", &c2c.stitch_lbr,
30343120
"Enable LBR callgraph stitching approach"),
30353121
OPT_BOOLEAN(0, "double-cl", &chk_double_cl, "Detect adjacent cacheline false sharing"),
3122+
OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
3123+
"Specify disassembler style (e.g. -M intel for intel syntax)"),
3124+
OPT_STRING(0, "objdump", &objdump_path, "path",
3125+
"objdump binary to use for disassembly and annotations"),
30363126
OPT_PARENT(c2c_options),
30373127
OPT_END()
30383128
};
30393129
int err = 0;
30403130
const char *output_str, *sort_str = NULL;
30413131
struct perf_env *env;
30423132

3133+
annotation_options__init();
3134+
3135+
err = hists__init();
3136+
if (err < 0)
3137+
goto out;
3138+
30433139
argc = parse_options(argc, argv, options, report_c2c_usage,
30443140
PARSE_OPT_STOP_AT_NON_OPTION);
30453141
if (argc)
@@ -3052,6 +3148,27 @@ static int perf_c2c__report(int argc, const char **argv)
30523148
if (c2c.stats_only)
30533149
c2c.use_stdio = true;
30543150

3151+
/**
3152+
* Annotation related options disassembler_style, objdump_path are set
3153+
* in the c2c_options, so we can use them here.
3154+
*/
3155+
if (disassembler_style) {
3156+
annotate_opts.disassembler_style = strdup(disassembler_style);
3157+
if (!annotate_opts.disassembler_style) {
3158+
err = -ENOMEM;
3159+
pr_err("Failed to allocate memory for annotation options\n");
3160+
goto out;
3161+
}
3162+
}
3163+
if (objdump_path) {
3164+
annotate_opts.objdump_path = strdup(objdump_path);
3165+
if (!annotate_opts.objdump_path) {
3166+
err = -ENOMEM;
3167+
pr_err("Failed to allocate memory for annotation options\n");
3168+
goto out;
3169+
}
3170+
}
3171+
30553172
err = symbol__validate_sym_arguments();
30563173
if (err)
30573174
goto out;
@@ -3126,6 +3243,38 @@ static int perf_c2c__report(int argc, const char **argv)
31263243
if (err)
31273244
goto out_mem2node;
31283245

3246+
if (c2c.use_stdio)
3247+
use_browser = 0;
3248+
else
3249+
use_browser = 1;
3250+
3251+
/*
3252+
* Only in the TUI browser we are doing integrated annotation,
3253+
* so don't allocate extra space that won't be used in the stdio
3254+
* implementation.
3255+
*/
3256+
if (perf_c2c__has_annotation(NULL)) {
3257+
int ret = symbol__annotation_init();
3258+
3259+
if (ret < 0)
3260+
goto out_mem2node;
3261+
/*
3262+
* For searching by name on the "Browse map details".
3263+
* providing it only in verbose mode not to bloat too
3264+
* much struct symbol.
3265+
*/
3266+
if (verbose > 0) {
3267+
/*
3268+
* XXX: Need to provide a less kludgy way to ask for
3269+
* more space per symbol, the u32 is for the index on
3270+
* the ui browser.
3271+
* See symbol__browser_index.
3272+
*/
3273+
symbol_conf.priv_size += sizeof(u32);
3274+
}
3275+
annotation_config__init();
3276+
}
3277+
31293278
if (symbol__init(env) < 0)
31303279
goto out_mem2node;
31313280

@@ -3135,11 +3284,6 @@ static int perf_c2c__report(int argc, const char **argv)
31353284
goto out_mem2node;
31363285
}
31373286

3138-
if (c2c.use_stdio)
3139-
use_browser = 0;
3140-
else
3141-
use_browser = 1;
3142-
31433287
setup_browser(false);
31443288

31453289
err = perf_session__process_events(session);
@@ -3210,6 +3354,7 @@ static int perf_c2c__report(int argc, const char **argv)
32103354
out_session:
32113355
perf_session__delete(session);
32123356
out:
3357+
annotation_options__exit();
32133358
return err;
32143359
}
32153360

0 commit comments

Comments
 (0)