Commit fc9c630e authored by Jiri Olsa's avatar Jiri Olsa Committed by Arnaldo Carvalho de Melo

perf c2c report: Allow to set cacheline sort fields

Allowing user to configure the way the single cacheline
data are sorted after being sorted by offset.

Adding 'c' option to specify sorting fields for single cacheline:

    -c, --coalesce <coalesce fields>
                          coalesce fields: pid,tid,iaddr,dso

It's allowed to use following combination of fields:
  pid   - process pid
  tid   - process tid
  iaddr - code address
  dso   - shared object
Tested-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Don Zickus <dzickus@redhat.com>
Cc: Joe Mario <jmario@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/n/tip-aka8z31umxoq2gqr5mjd81zr@git.kernel.orgSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 55b95776
...@@ -46,6 +46,8 @@ struct c2c_hist_entry { ...@@ -46,6 +46,8 @@ struct c2c_hist_entry {
struct hist_entry he; struct hist_entry he;
}; };
static char const *coalesce_default = "pid,tid,iaddr";
struct perf_c2c { struct perf_c2c {
struct perf_tool tool; struct perf_tool tool;
struct c2c_hists hists; struct c2c_hists hists;
...@@ -65,6 +67,11 @@ struct perf_c2c { ...@@ -65,6 +67,11 @@ struct perf_c2c {
int shared_clines; int shared_clines;
int display; int display;
const char *coalesce;
char *cl_sort;
char *cl_resort;
char *cl_output;
}; };
enum { enum {
...@@ -239,7 +246,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused, ...@@ -239,7 +246,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
if (!mi_dup) if (!mi_dup)
goto free_mi; goto free_mi;
c2c_hists = he__get_c2c_hists(he, "offset", 2); c2c_hists = he__get_c2c_hists(he, c2c.cl_sort, 2);
if (!c2c_hists) if (!c2c_hists)
goto free_mi_dup; goto free_mi_dup;
...@@ -1742,22 +1749,7 @@ static int resort_cl_cb(struct hist_entry *he) ...@@ -1742,22 +1749,7 @@ static int resort_cl_cb(struct hist_entry *he)
c2c_hists = c2c_he->hists; c2c_hists = c2c_he->hists;
if (display && c2c_hists) { if (display && c2c_hists) {
c2c_hists__reinit(c2c_hists, c2c_hists__reinit(c2c_hists, c2c.cl_output, c2c.cl_resort);
"percent_rmt_hitm,"
"percent_lcl_hitm,"
"percent_stores_l1hit,"
"percent_stores_l1miss,"
"offset,"
"pid,"
"tid,"
"mean_rmt,"
"mean_lcl,"
"mean_load,"
"cpucnt,"
"symbol,"
"dso,"
"node",
"offset,rmt_hitm,lcl_hitm");
hists__collapse_resort(&c2c_hists->hists, NULL); hists__collapse_resort(&c2c_hists->hists, NULL);
hists__output_resort_cb(&c2c_hists->hists, NULL, filter_cb); hists__output_resort_cb(&c2c_hists->hists, NULL, filter_cb);
...@@ -2001,6 +1993,7 @@ static void print_c2c_info(FILE *out, struct perf_session *session) ...@@ -2001,6 +1993,7 @@ static void print_c2c_info(FILE *out, struct perf_session *session)
} }
fprintf(out, " Cachelines sort on : %s HITMs\n", fprintf(out, " Cachelines sort on : %s HITMs\n",
c2c.display == DISPLAY_LCL ? "Local" : "Remote"); c2c.display == DISPLAY_LCL ? "Local" : "Remote");
fprintf(out, " Cacheline data grouping : %s\n", c2c.cl_sort);
} }
static void perf_c2c__hists_fprintf(FILE *out, struct perf_session *session) static void perf_c2c__hists_fprintf(FILE *out, struct perf_session *session)
...@@ -2280,6 +2273,89 @@ static int setup_display(const char *str) ...@@ -2280,6 +2273,89 @@ static int setup_display(const char *str)
return 0; return 0;
} }
#define for_each_token(__tok, __buf, __sep, __tmp) \
for (__tok = strtok_r(__buf, __sep, &__tmp); __tok; \
__tok = strtok_r(NULL, __sep, &__tmp))
static int build_cl_output(char *cl_sort)
{
char *tok, *tmp, *buf = strdup(cl_sort);
bool add_pid = false;
bool add_tid = false;
bool add_iaddr = false;
bool add_sym = false;
bool add_dso = false;
bool add_src = false;
if (!buf)
return -ENOMEM;
for_each_token(tok, buf, ",", tmp) {
if (!strcmp(tok, "tid")) {
add_tid = true;
} else if (!strcmp(tok, "pid")) {
add_pid = true;
} else if (!strcmp(tok, "iaddr")) {
add_iaddr = true;
add_sym = true;
add_dso = true;
add_src = true;
} else if (!strcmp(tok, "dso")) {
add_dso = true;
} else if (strcmp(tok, "offset")) {
pr_err("unrecognized sort token: %s\n", tok);
return -EINVAL;
}
}
if (asprintf(&c2c.cl_output,
"%s%s%s%s%s%s%s%s%s",
"percent_rmt_hitm,"
"percent_lcl_hitm,"
"percent_stores_l1hit,"
"percent_stores_l1miss,"
"offset,",
add_pid ? "pid," : "",
add_tid ? "tid," : "",
add_iaddr ? "iaddr," : "",
"mean_rmt,"
"mean_lcl,"
"mean_load,"
"cpucnt,",
add_sym ? "symbol," : "",
add_dso ? "dso," : "",
add_src ? "cl_srcline," : "",
"node") < 0)
return -ENOMEM;
c2c.show_src = add_src;
free(buf);
return 0;
}
static int setup_coalesce(const char *coalesce)
{
const char *c = coalesce ?: coalesce_default;
if (asprintf(&c2c.cl_sort, "offset,%s", c) < 0)
return -ENOMEM;
if (build_cl_output(c2c.cl_sort))
return -1;
if (asprintf(&c2c.cl_resort, "offset,%s",
c2c.display == DISPLAY_RMT ?
"rmt_hitm,lcl_hitm" :
"lcl_hitm,rmt_hitm") < 0)
return -ENOMEM;
pr_debug("coalesce sort fields: %s\n", c2c.cl_sort);
pr_debug("coalesce resort fields: %s\n", c2c.cl_resort);
pr_debug("coalesce output fields: %s\n", c2c.cl_output);
return 0;
}
static int perf_c2c__report(int argc, const char **argv) static int perf_c2c__report(int argc, const char **argv)
{ {
struct perf_session *session; struct perf_session *session;
...@@ -2289,6 +2365,7 @@ static int perf_c2c__report(int argc, const char **argv) ...@@ -2289,6 +2365,7 @@ static int perf_c2c__report(int argc, const char **argv)
}; };
char callchain_default_opt[] = CALLCHAIN_DEFAULT_OPT; char callchain_default_opt[] = CALLCHAIN_DEFAULT_OPT;
const char *display = NULL; const char *display = NULL;
const char *coalesce = NULL;
const struct option c2c_options[] = { const struct option c2c_options[] = {
OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
"file", "vmlinux pathname"), "file", "vmlinux pathname"),
...@@ -2308,6 +2385,8 @@ static int perf_c2c__report(int argc, const char **argv) ...@@ -2308,6 +2385,8 @@ static int perf_c2c__report(int argc, const char **argv)
callchain_help, &parse_callchain_opt, callchain_help, &parse_callchain_opt,
callchain_default_opt), callchain_default_opt),
OPT_STRING('d', "display", &display, NULL, "lcl,rmt"), OPT_STRING('d', "display", &display, NULL, "lcl,rmt"),
OPT_STRING('c', "coalesce", &coalesce, "coalesce fields",
"coalesce fields: pid,tid,iaddr,dso"),
OPT_END() OPT_END()
}; };
int err = 0; int err = 0;
...@@ -2336,6 +2415,12 @@ static int perf_c2c__report(int argc, const char **argv) ...@@ -2336,6 +2415,12 @@ static int perf_c2c__report(int argc, const char **argv)
if (err) if (err)
goto out; goto out;
err = setup_coalesce(coalesce);
if (err) {
pr_debug("Failed to initialize hists\n");
goto out;
}
err = c2c_hists__init(&c2c.hists, "dcacheline", 2); err = c2c_hists__init(&c2c.hists, "dcacheline", 2);
if (err) { if (err) {
pr_debug("Failed to initialize hists\n"); pr_debug("Failed to initialize hists\n");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment