diff options
author | Jiri Olsa <jolsa@kernel.org> | 2016-01-06 10:59:02 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2016-10-21 09:30:03 -0400 |
commit | 5a1a99cd2e4e15571a74f65facf05f806d5303fd (patch) | |
tree | 964439c4681439801ad20105bb0db1b70e2424b4 /tools | |
parent | 2d388bd0c9d3e3fed9e4abdd9aadf2f07e9cf755 (diff) |
perf c2c report: Add main TUI browser
Add the main cachelines TUI browser. It allows to navigate through
cachelines and display their details and callchains (implemented in the
following patches).
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: Kim Phillips <kim.phillips@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/n/tip-pk632k4h1uwc5t0lqc7k61zg@git.kernel.org
Link: http://lkml.kernel.org/r/20161021001706.GB23970@krava
[ Handle file with no entries, fixing segfault reported by Kim Phillips ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/builtin-c2c.c | 117 | ||||
-rw-r--r-- | tools/perf/ui/browsers/hists.c | 2 | ||||
-rw-r--r-- | tools/perf/ui/browsers/hists.h | 1 |
3 files changed, 117 insertions, 3 deletions
diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c index 33db26c6ca63..34da2a3975b0 100644 --- a/tools/perf/builtin-c2c.c +++ b/tools/perf/builtin-c2c.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include "data.h" | 14 | #include "data.h" |
15 | #include "sort.h" | 15 | #include "sort.h" |
16 | #include <asm/bug.h> | 16 | #include <asm/bug.h> |
17 | #include "ui/browsers/hists.h" | ||
17 | 18 | ||
18 | struct c2c_hists { | 19 | struct c2c_hists { |
19 | struct hists hists; | 20 | struct hists hists; |
@@ -53,6 +54,7 @@ struct perf_c2c { | |||
53 | int node_info; | 54 | int node_info; |
54 | 55 | ||
55 | bool show_src; | 56 | bool show_src; |
57 | bool use_stdio; | ||
56 | }; | 58 | }; |
57 | 59 | ||
58 | static struct perf_c2c c2c; | 60 | static struct perf_c2c c2c; |
@@ -657,6 +659,10 @@ percent_color(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, | |||
657 | c2c_he = container_of(he, struct c2c_hist_entry, he); | 659 | c2c_he = container_of(he, struct c2c_hist_entry, he); |
658 | per = get_percent(c2c_he); | 660 | per = get_percent(c2c_he); |
659 | 661 | ||
662 | #ifdef HAVE_SLANG_SUPPORT | ||
663 | if (use_browser) | ||
664 | return __hpp__slsmg_color_printf(hpp, "%*.2f%%", width - 1, per); | ||
665 | #endif | ||
660 | return hpp_color_scnprintf(hpp, "%*.2f%%", width - 1, per); | 666 | return hpp_color_scnprintf(hpp, "%*.2f%%", width - 1, per); |
661 | } | 667 | } |
662 | 668 | ||
@@ -1077,6 +1083,8 @@ static struct c2c_dimension dim_dcacheline = { | |||
1077 | .width = 18, | 1083 | .width = 18, |
1078 | }; | 1084 | }; |
1079 | 1085 | ||
1086 | static struct c2c_header header_offset_tui = HEADER_LOW("Off"); | ||
1087 | |||
1080 | static struct c2c_dimension dim_offset = { | 1088 | static struct c2c_dimension dim_offset = { |
1081 | .header = HEADER_BOTH("Data address", "Offset"), | 1089 | .header = HEADER_BOTH("Data address", "Offset"), |
1082 | .name = "offset", | 1090 | .name = "offset", |
@@ -1803,6 +1811,100 @@ static void perf_c2c__hists_fprintf(FILE *out) | |||
1803 | print_pareto(out); | 1811 | print_pareto(out); |
1804 | } | 1812 | } |
1805 | 1813 | ||
1814 | #ifdef HAVE_SLANG_SUPPORT | ||
1815 | static void c2c_browser__update_nr_entries(struct hist_browser *hb) | ||
1816 | { | ||
1817 | u64 nr_entries = 0; | ||
1818 | struct rb_node *nd = rb_first(&hb->hists->entries); | ||
1819 | |||
1820 | while (nd) { | ||
1821 | struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node); | ||
1822 | |||
1823 | if (!he->filtered) | ||
1824 | nr_entries++; | ||
1825 | |||
1826 | nd = rb_next(nd); | ||
1827 | } | ||
1828 | |||
1829 | hb->nr_non_filtered_entries = nr_entries; | ||
1830 | } | ||
1831 | |||
1832 | static int perf_c2c_browser__title(struct hist_browser *browser, | ||
1833 | char *bf, size_t size) | ||
1834 | { | ||
1835 | scnprintf(bf, size, | ||
1836 | "Shared Data Cache Line Table " | ||
1837 | "(%lu entries)", browser->nr_non_filtered_entries); | ||
1838 | return 0; | ||
1839 | } | ||
1840 | |||
1841 | static struct hist_browser* | ||
1842 | perf_c2c_browser__new(struct hists *hists) | ||
1843 | { | ||
1844 | struct hist_browser *browser = hist_browser__new(hists); | ||
1845 | |||
1846 | if (browser) { | ||
1847 | browser->title = perf_c2c_browser__title; | ||
1848 | browser->c2c_filter = true; | ||
1849 | } | ||
1850 | |||
1851 | return browser; | ||
1852 | } | ||
1853 | |||
1854 | static int perf_c2c__hists_browse(struct hists *hists) | ||
1855 | { | ||
1856 | struct hist_browser *browser; | ||
1857 | int key = -1; | ||
1858 | |||
1859 | browser = perf_c2c_browser__new(hists); | ||
1860 | if (browser == NULL) | ||
1861 | return -1; | ||
1862 | |||
1863 | /* reset abort key so that it can get Ctrl-C as a key */ | ||
1864 | SLang_reset_tty(); | ||
1865 | SLang_init_tty(0, 0, 0); | ||
1866 | |||
1867 | c2c_browser__update_nr_entries(browser); | ||
1868 | |||
1869 | while (1) { | ||
1870 | key = hist_browser__run(browser, "help"); | ||
1871 | |||
1872 | switch (key) { | ||
1873 | case 'q': | ||
1874 | goto out; | ||
1875 | default: | ||
1876 | break; | ||
1877 | } | ||
1878 | } | ||
1879 | |||
1880 | out: | ||
1881 | hist_browser__delete(browser); | ||
1882 | return 0; | ||
1883 | } | ||
1884 | |||
1885 | static void perf_c2c_display(void) | ||
1886 | { | ||
1887 | if (c2c.use_stdio) | ||
1888 | perf_c2c__hists_fprintf(stdout); | ||
1889 | else | ||
1890 | perf_c2c__hists_browse(&c2c.hists.hists); | ||
1891 | } | ||
1892 | #else | ||
1893 | static void perf_c2c_display(void) | ||
1894 | { | ||
1895 | use_browser = 0; | ||
1896 | perf_c2c__hists_fprintf(stdout); | ||
1897 | } | ||
1898 | #endif /* HAVE_SLANG_SUPPORT */ | ||
1899 | |||
1900 | static void ui_quirks(void) | ||
1901 | { | ||
1902 | if (!c2c.use_stdio) { | ||
1903 | dim_offset.width = 5; | ||
1904 | dim_offset.header = header_offset_tui; | ||
1905 | } | ||
1906 | } | ||
1907 | |||
1806 | static int perf_c2c__report(int argc, const char **argv) | 1908 | static int perf_c2c__report(int argc, const char **argv) |
1807 | { | 1909 | { |
1808 | struct perf_session *session; | 1910 | struct perf_session *session; |
@@ -1819,6 +1921,9 @@ static int perf_c2c__report(int argc, const char **argv) | |||
1819 | "the input file to process"), | 1921 | "the input file to process"), |
1820 | OPT_INCR('N', "node-info", &c2c.node_info, | 1922 | OPT_INCR('N', "node-info", &c2c.node_info, |
1821 | "show extra node info in report (repeat for more info)"), | 1923 | "show extra node info in report (repeat for more info)"), |
1924 | #ifdef HAVE_SLANG_SUPPORT | ||
1925 | OPT_BOOLEAN(0, "stdio", &c2c.use_stdio, "Use the stdio interface"), | ||
1926 | #endif | ||
1822 | OPT_END() | 1927 | OPT_END() |
1823 | }; | 1928 | }; |
1824 | int err = 0; | 1929 | int err = 0; |
@@ -1828,6 +1933,13 @@ static int perf_c2c__report(int argc, const char **argv) | |||
1828 | if (argc) | 1933 | if (argc) |
1829 | usage_with_options(report_c2c_usage, c2c_options); | 1934 | usage_with_options(report_c2c_usage, c2c_options); |
1830 | 1935 | ||
1936 | if (c2c.use_stdio) | ||
1937 | use_browser = 0; | ||
1938 | else | ||
1939 | use_browser = 1; | ||
1940 | |||
1941 | setup_browser(false); | ||
1942 | |||
1831 | if (!input_name || !strlen(input_name)) | 1943 | if (!input_name || !strlen(input_name)) |
1832 | input_name = "perf.data"; | 1944 | input_name = "perf.data"; |
1833 | 1945 | ||
@@ -1886,8 +1998,9 @@ static int perf_c2c__report(int argc, const char **argv) | |||
1886 | 1998 | ||
1887 | ui_progress__finish(); | 1999 | ui_progress__finish(); |
1888 | 2000 | ||
1889 | use_browser = 0; | 2001 | ui_quirks(); |
1890 | perf_c2c__hists_fprintf(stdout); | 2002 | |
2003 | perf_c2c_display(); | ||
1891 | 2004 | ||
1892 | out_session: | 2005 | out_session: |
1893 | perf_session__delete(session); | 2006 | perf_session__delete(session); |
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 4ffff7be9299..31d6d5a7c2dc 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c | |||
@@ -30,7 +30,7 @@ static struct rb_node *hists__filter_entries(struct rb_node *nd, | |||
30 | 30 | ||
31 | static bool hist_browser__has_filter(struct hist_browser *hb) | 31 | static bool hist_browser__has_filter(struct hist_browser *hb) |
32 | { | 32 | { |
33 | return hists__has_filter(hb->hists) || hb->min_pcnt || symbol_conf.has_filter; | 33 | return hists__has_filter(hb->hists) || hb->min_pcnt || symbol_conf.has_filter || hb->c2c_filter; |
34 | } | 34 | } |
35 | 35 | ||
36 | static int hist_browser__get_folding(struct hist_browser *browser) | 36 | static int hist_browser__get_folding(struct hist_browser *browser) |
diff --git a/tools/perf/ui/browsers/hists.h b/tools/perf/ui/browsers/hists.h index 39bd0f28f211..23d6acb84800 100644 --- a/tools/perf/ui/browsers/hists.h +++ b/tools/perf/ui/browsers/hists.h | |||
@@ -18,6 +18,7 @@ struct hist_browser { | |||
18 | u64 nr_non_filtered_entries; | 18 | u64 nr_non_filtered_entries; |
19 | u64 nr_hierarchy_entries; | 19 | u64 nr_hierarchy_entries; |
20 | u64 nr_callchain_rows; | 20 | u64 nr_callchain_rows; |
21 | bool c2c_filter; | ||
21 | 22 | ||
22 | /* Get title string. */ | 23 | /* Get title string. */ |
23 | int (*title)(struct hist_browser *browser, | 24 | int (*title)(struct hist_browser *browser, |