aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorJiri Olsa <jolsa@kernel.org>2016-05-29 04:21:45 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2016-10-21 09:31:57 -0400
commit55b9577672b27f71843c07b9958129c4548a4090 (patch)
treedbdf7d8d26a3278e07f489931c96bf4e63c947c1 /tools/perf
parent9857b7173cf420654a7a78a2cdf972ddb380a8a1 (diff)
perf c2c report: Add support to choose local HITMs
Currently we sort and limit displayed data based on the remote HITMs count. Adding support to switch to local HITMs via --display option: --display ... lcl,rmt Signed-off-by: Jiri Olsa <jolsa@kernel.org> Tested-by: Arnaldo 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-inykbom2f19difvsu1e18avr@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/builtin-c2c.c114
1 files changed, 95 insertions, 19 deletions
diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c
index 92b3b8171d4d..75bcf1406df3 100644
--- a/tools/perf/builtin-c2c.c
+++ b/tools/perf/builtin-c2c.c
@@ -63,6 +63,13 @@ struct perf_c2c {
63 /* HITM shared clines stats */ 63 /* HITM shared clines stats */
64 struct c2c_stats hitm_stats; 64 struct c2c_stats hitm_stats;
65 int shared_clines; 65 int shared_clines;
66
67 int display;
68};
69
70enum {
71 DISPLAY_LCL,
72 DISPLAY_RMT,
66}; 73};
67 74
68static struct perf_c2c c2c; 75static struct perf_c2c c2c;
@@ -684,15 +691,24 @@ static double percent_hitm(struct c2c_hist_entry *c2c_he)
684 struct c2c_hists *hists; 691 struct c2c_hists *hists;
685 struct c2c_stats *stats; 692 struct c2c_stats *stats;
686 struct c2c_stats *total; 693 struct c2c_stats *total;
687 int tot, st; 694 int tot = 0, st = 0;
688 double p; 695 double p;
689 696
690 hists = container_of(c2c_he->he.hists, struct c2c_hists, hists); 697 hists = container_of(c2c_he->he.hists, struct c2c_hists, hists);
691 stats = &c2c_he->stats; 698 stats = &c2c_he->stats;
692 total = &hists->stats; 699 total = &hists->stats;
693 700
694 st = stats->rmt_hitm; 701 switch (c2c.display) {
695 tot = total->rmt_hitm; 702 case DISPLAY_RMT:
703 st = stats->rmt_hitm;
704 tot = total->rmt_hitm;
705 break;
706 case DISPLAY_LCL:
707 st = stats->lcl_hitm;
708 tot = total->lcl_hitm;
709 default:
710 break;
711 }
696 712
697 p = tot ? (double) st / tot : 0; 713 p = tot ? (double) st / tot : 0;
698 714
@@ -975,14 +991,26 @@ node_entry(struct perf_hpp_fmt *fmt __maybe_unused, struct perf_hpp *hpp,
975 ret = scnprintf(hpp->buf, hpp->size, "%2d{%2d ", node, num); 991 ret = scnprintf(hpp->buf, hpp->size, "%2d{%2d ", node, num);
976 advance_hpp(hpp, ret); 992 advance_hpp(hpp, ret);
977 993
994 #define DISPLAY_HITM(__h) \
995 if (c2c_he->stats.__h> 0) { \
996 ret = scnprintf(hpp->buf, hpp->size, "%5.1f%% ", \
997 percent(stats->__h, c2c_he->stats.__h));\
998 } else { \
999 ret = scnprintf(hpp->buf, hpp->size, "%6s ", "n/a"); \
1000 }
978 1001
979 if (c2c_he->stats.rmt_hitm > 0) { 1002 switch (c2c.display) {
980 ret = scnprintf(hpp->buf, hpp->size, "%5.1f%% ", 1003 case DISPLAY_RMT:
981 percent(stats->rmt_hitm, c2c_he->stats.rmt_hitm)); 1004 DISPLAY_HITM(rmt_hitm);
982 } else { 1005 break;
983 ret = scnprintf(hpp->buf, hpp->size, "%6s ", "n/a"); 1006 case DISPLAY_LCL:
1007 DISPLAY_HITM(lcl_hitm);
1008 default:
1009 break;
984 } 1010 }
985 1011
1012 #undef DISPLAY_HITM
1013
986 advance_hpp(hpp, ret); 1014 advance_hpp(hpp, ret);
987 1015
988 if (c2c_he->stats.store > 0) { 1016 if (c2c_he->stats.store > 0) {
@@ -1258,8 +1286,12 @@ static struct c2c_dimension dim_tot_loads = {
1258 .width = 7, 1286 .width = 7,
1259}; 1287};
1260 1288
1289static struct c2c_header percent_hitm_header[] = {
1290 [DISPLAY_LCL] = HEADER_BOTH("Lcl", "Hitm"),
1291 [DISPLAY_RMT] = HEADER_BOTH("Rmt", "Hitm"),
1292};
1293
1261static struct c2c_dimension dim_percent_hitm = { 1294static struct c2c_dimension dim_percent_hitm = {
1262 .header = HEADER_LOW("%hitm"),
1263 .name = "percent_hitm", 1295 .name = "percent_hitm",
1264 .cmp = percent_hitm_cmp, 1296 .cmp = percent_hitm_cmp,
1265 .entry = percent_hitm_entry, 1297 .entry = percent_hitm_entry,
@@ -1654,23 +1686,39 @@ static bool he__display(struct hist_entry *he, struct c2c_stats *stats)
1654 1686
1655 c2c_he = container_of(he, struct c2c_hist_entry, he); 1687 c2c_he = container_of(he, struct c2c_hist_entry, he);
1656 1688
1657 if (stats->rmt_hitm) { 1689#define FILTER_HITM(__h) \
1658 ld_dist = ((double)c2c_he->stats.rmt_hitm / stats->rmt_hitm); 1690 if (stats->__h) { \
1659 if (ld_dist < DISPLAY_LINE_LIMIT) 1691 ld_dist = ((double)c2c_he->stats.__h / stats->__h); \
1660 he->filtered = HIST_FILTER__C2C; 1692 if (ld_dist < DISPLAY_LINE_LIMIT) \
1661 } else { 1693 he->filtered = HIST_FILTER__C2C; \
1662 he->filtered = HIST_FILTER__C2C; 1694 } else { \
1695 he->filtered = HIST_FILTER__C2C; \
1663 } 1696 }
1664 1697
1698 switch (c2c.display) {
1699 case DISPLAY_LCL:
1700 FILTER_HITM(lcl_hitm);
1701 break;
1702 case DISPLAY_RMT:
1703 FILTER_HITM(rmt_hitm);
1704 default:
1705 break;
1706 };
1707
1708#undef FILTER_HITM
1709
1665 return he->filtered == 0; 1710 return he->filtered == 0;
1666} 1711}
1667 1712
1668static inline int valid_hitm_or_store(struct hist_entry *he) 1713static inline int valid_hitm_or_store(struct hist_entry *he)
1669{ 1714{
1670 struct c2c_hist_entry *c2c_he; 1715 struct c2c_hist_entry *c2c_he;
1716 bool has_hitm;
1671 1717
1672 c2c_he = container_of(he, struct c2c_hist_entry, he); 1718 c2c_he = container_of(he, struct c2c_hist_entry, he);
1673 return c2c_he->stats.rmt_hitm || c2c_he->stats.store; 1719 has_hitm = c2c.display == DISPLAY_LCL ?
1720 c2c_he->stats.lcl_hitm : c2c_he->stats.rmt_hitm;
1721 return has_hitm || c2c_he->stats.store;
1674} 1722}
1675 1723
1676static int filter_cb(struct hist_entry *he) 1724static int filter_cb(struct hist_entry *he)
@@ -1951,6 +1999,8 @@ static void print_c2c_info(FILE *out, struct perf_session *session)
1951 perf_evsel__name(evsel)); 1999 perf_evsel__name(evsel));
1952 first = false; 2000 first = false;
1953 } 2001 }
2002 fprintf(out, " Cachelines sort on : %s HITMs\n",
2003 c2c.display == DISPLAY_LCL ? "Local" : "Remote");
1954} 2004}
1955 2005
1956static void perf_c2c__hists_fprintf(FILE *out, struct perf_session *session) 2006static void perf_c2c__hists_fprintf(FILE *out, struct perf_session *session)
@@ -2083,8 +2133,10 @@ static int perf_c2c_browser__title(struct hist_browser *browser,
2083 char *bf, size_t size) 2133 char *bf, size_t size)
2084{ 2134{
2085 scnprintf(bf, size, 2135 scnprintf(bf, size,
2086 "Shared Data Cache Line Table " 2136 "Shared Data Cache Line Table "
2087 "(%lu entries)", browser->nr_non_filtered_entries); 2137 "(%lu entries, sorted on %s HITMs)",
2138 browser->nr_non_filtered_entries,
2139 c2c.display == DISPLAY_LCL ? "local" : "remote");
2088 return 0; 2140 return 0;
2089} 2141}
2090 2142
@@ -2156,6 +2208,8 @@ static void ui_quirks(void)
2156 dim_offset.width = 5; 2208 dim_offset.width = 5;
2157 dim_offset.header = header_offset_tui; 2209 dim_offset.header = header_offset_tui;
2158 } 2210 }
2211
2212 dim_percent_hitm.header = percent_hitm_header[c2c.display];
2159} 2213}
2160 2214
2161#define CALLCHAIN_DEFAULT_OPT "graph,0.5,caller,function,percent" 2215#define CALLCHAIN_DEFAULT_OPT "graph,0.5,caller,function,percent"
@@ -2210,6 +2264,22 @@ static int setup_callchain(struct perf_evlist *evlist)
2210 return 0; 2264 return 0;
2211} 2265}
2212 2266
2267static int setup_display(const char *str)
2268{
2269 const char *display = str ?: "rmt";
2270
2271 if (!strcmp(display, "rmt"))
2272 c2c.display = DISPLAY_RMT;
2273 else if (!strcmp(display, "lcl"))
2274 c2c.display = DISPLAY_LCL;
2275 else {
2276 pr_err("failed: unknown display type: %s\n", str);
2277 return -1;
2278 }
2279
2280 return 0;
2281}
2282
2213static int perf_c2c__report(int argc, const char **argv) 2283static int perf_c2c__report(int argc, const char **argv)
2214{ 2284{
2215 struct perf_session *session; 2285 struct perf_session *session;
@@ -2218,6 +2288,7 @@ static int perf_c2c__report(int argc, const char **argv)
2218 .mode = PERF_DATA_MODE_READ, 2288 .mode = PERF_DATA_MODE_READ,
2219 }; 2289 };
2220 char callchain_default_opt[] = CALLCHAIN_DEFAULT_OPT; 2290 char callchain_default_opt[] = CALLCHAIN_DEFAULT_OPT;
2291 const char *display = NULL;
2221 const struct option c2c_options[] = { 2292 const struct option c2c_options[] = {
2222 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 2293 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
2223 "file", "vmlinux pathname"), 2294 "file", "vmlinux pathname"),
@@ -2236,6 +2307,7 @@ static int perf_c2c__report(int argc, const char **argv)
2236 "print_type,threshold[,print_limit],order,sort_key[,branch],value", 2307 "print_type,threshold[,print_limit],order,sort_key[,branch],value",
2237 callchain_help, &parse_callchain_opt, 2308 callchain_help, &parse_callchain_opt,
2238 callchain_default_opt), 2309 callchain_default_opt),
2310 OPT_STRING('d', "display", &display, NULL, "lcl,rmt"),
2239 OPT_END() 2311 OPT_END()
2240 }; 2312 };
2241 int err = 0; 2313 int err = 0;
@@ -2260,6 +2332,10 @@ static int perf_c2c__report(int argc, const char **argv)
2260 2332
2261 file.path = input_name; 2333 file.path = input_name;
2262 2334
2335 err = setup_display(display);
2336 if (err)
2337 goto out;
2338
2263 err = c2c_hists__init(&c2c.hists, "dcacheline", 2); 2339 err = c2c_hists__init(&c2c.hists, "dcacheline", 2);
2264 if (err) { 2340 if (err) {
2265 pr_debug("Failed to initialize hists\n"); 2341 pr_debug("Failed to initialize hists\n");
@@ -2307,7 +2383,7 @@ static int perf_c2c__report(int argc, const char **argv)
2307 "tot_loads," 2383 "tot_loads,"
2308 "ld_fbhit,ld_l1hit,ld_l2hit," 2384 "ld_fbhit,ld_l1hit,ld_l2hit,"
2309 "ld_lclhit,ld_rmthit", 2385 "ld_lclhit,ld_rmthit",
2310 "rmt_hitm" 2386 c2c.display == DISPLAY_LCL ? "lcl_hitm" : "rmt_hitm"
2311 ); 2387 );
2312 2388
2313 ui_progress__init(&prog, c2c.hists.hists.nr_entries, "Sorting..."); 2389 ui_progress__init(&prog, c2c.hists.hists.nr_entries, "Sorting...");