aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2018-03-15 22:44:34 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2018-03-21 11:53:26 -0400
commitbefd2a38a632b1f27ad652fea67c8cf97ce59409 (patch)
tree8389138ba03f646ed5467ef39c1d8b905465cd96
parent9b80d1f946ee40923f7bf51c69cb3a6ac6097e4a (diff)
perf annotate: Introduce the --stdio2 output mode
This uses the TUI augmented formatting routines, modulo interactivity. # perf annotate --ignore-vmlinux --stdio2 _raw_spin_lock_irqsave _raw_spin_lock_irqsave() /proc/kcore Event: cycles:ppp Percent Disassembly of section load0: ffffffff9a8734b0 <load0>: nop push %rbx 50.00 pushfq pop %rax nop mov %rax,%rbx cli nop xor %eax,%eax mov $0x1,%edx 50.00 lock cmpxchg %edx,(%rdi) test %eax,%eax ↓ jne 2b mov %rbx,%rax pop %rbx ← retq 2b: mov %eax,%esi → callq queued_spin_lock_slowpath mov %rbx,%rax pop %rbx ← retq Tested-by: Jin Yao <yao.jin@linux.intel.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: David Ahern <dsahern@gmail.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Wang Nan <wangnan0@huawei.com> Link: https://lkml.kernel.org/n/tip-6cte5o8z84mbivbvqlg14uh1@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/Documentation/perf-annotate.txt2
-rw-r--r--tools/perf/builtin-annotate.c23
-rw-r--r--tools/perf/util/annotate.c92
-rw-r--r--tools/perf/util/annotate.h5
4 files changed, 115 insertions, 7 deletions
diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt
index 292809c3c0ca..c29c7fc93023 100644
--- a/tools/perf/Documentation/perf-annotate.txt
+++ b/tools/perf/Documentation/perf-annotate.txt
@@ -69,6 +69,8 @@ OPTIONS
69 69
70--stdio:: Use the stdio interface. 70--stdio:: Use the stdio interface.
71 71
72--stdio2:: Use the stdio2 interface, non-interactive, uses the TUI formatting.
73
72--stdio-color=<mode>:: 74--stdio-color=<mode>::
73 'always', 'never' or 'auto', allowing configuring color output 75 'always', 'never' or 'auto', allowing configuring color output
74 via the command line, in addition to via "color.ui" .perfconfig. 76 via the command line, in addition to via "color.ui" .perfconfig.
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index ead6ae4549e5..e03f9bea9303 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -40,7 +40,7 @@
40struct perf_annotate { 40struct perf_annotate {
41 struct perf_tool tool; 41 struct perf_tool tool;
42 struct perf_session *session; 42 struct perf_session *session;
43 bool use_tui, use_stdio, use_gtk; 43 bool use_tui, use_stdio, use_stdio2, use_gtk;
44 bool full_paths; 44 bool full_paths;
45 bool print_line; 45 bool print_line;
46 bool skip_missing; 46 bool skip_missing;
@@ -202,6 +202,11 @@ static int process_branch_callback(struct perf_evsel *evsel,
202 return ret; 202 return ret;
203} 203}
204 204
205static bool has_annotation(struct perf_annotate *ann)
206{
207 return ui__has_annotation() || ann->use_stdio2;
208}
209
205static int perf_evsel__add_sample(struct perf_evsel *evsel, 210static int perf_evsel__add_sample(struct perf_evsel *evsel,
206 struct perf_sample *sample, 211 struct perf_sample *sample,
207 struct addr_location *al, 212 struct addr_location *al,
@@ -212,7 +217,7 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
212 struct hist_entry *he; 217 struct hist_entry *he;
213 int ret; 218 int ret;
214 219
215 if ((!ann->has_br_stack || !ui__has_annotation()) && 220 if ((!ann->has_br_stack || !has_annotation(ann)) &&
216 ann->sym_hist_filter != NULL && 221 ann->sym_hist_filter != NULL &&
217 (al->sym == NULL || 222 (al->sym == NULL ||
218 strcmp(ann->sym_hist_filter, al->sym->name) != 0)) { 223 strcmp(ann->sym_hist_filter, al->sym->name) != 0)) {
@@ -236,7 +241,7 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
236 */ 241 */
237 process_branch_stack(sample->branch_stack, al, sample); 242 process_branch_stack(sample->branch_stack, al, sample);
238 243
239 if (ann->has_br_stack && ui__has_annotation()) 244 if (ann->has_br_stack && has_annotation(ann))
240 return process_branch_callback(evsel, sample, al, ann, machine); 245 return process_branch_callback(evsel, sample, al, ann, machine);
241 246
242 he = hists__add_entry(hists, al, NULL, NULL, NULL, sample, true); 247 he = hists__add_entry(hists, al, NULL, NULL, NULL, sample, true);
@@ -282,8 +287,11 @@ static int hist_entry__tty_annotate(struct hist_entry *he,
282 struct perf_evsel *evsel, 287 struct perf_evsel *evsel,
283 struct perf_annotate *ann) 288 struct perf_annotate *ann)
284{ 289{
285 return symbol__tty_annotate(he->ms.sym, he->ms.map, evsel, 290 if (!ann->use_stdio2)
286 ann->print_line, ann->full_paths, 0, 0); 291 return symbol__tty_annotate(he->ms.sym, he->ms.map, evsel,
292 ann->print_line, ann->full_paths, 0, 0);
293 return symbol__tty_annotate2(he->ms.sym, he->ms.map, evsel,
294 ann->print_line, ann->full_paths);
287} 295}
288 296
289static void hists__find_annotations(struct hists *hists, 297static void hists__find_annotations(struct hists *hists,
@@ -487,6 +495,7 @@ int cmd_annotate(int argc, const char **argv)
487 OPT_BOOLEAN(0, "gtk", &annotate.use_gtk, "Use the GTK interface"), 495 OPT_BOOLEAN(0, "gtk", &annotate.use_gtk, "Use the GTK interface"),
488 OPT_BOOLEAN(0, "tui", &annotate.use_tui, "Use the TUI interface"), 496 OPT_BOOLEAN(0, "tui", &annotate.use_tui, "Use the TUI interface"),
489 OPT_BOOLEAN(0, "stdio", &annotate.use_stdio, "Use the stdio interface"), 497 OPT_BOOLEAN(0, "stdio", &annotate.use_stdio, "Use the stdio interface"),
498 OPT_BOOLEAN(0, "stdio2", &annotate.use_stdio2, "Use the stdio interface"),
490 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 499 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
491 "file", "vmlinux pathname"), 500 "file", "vmlinux pathname"),
492 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules, 501 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
@@ -569,7 +578,7 @@ int cmd_annotate(int argc, const char **argv)
569 if (ret < 0) 578 if (ret < 0)
570 goto out_delete; 579 goto out_delete;
571 580
572 if (annotate.use_stdio) 581 if (annotate.use_stdio || annotate.use_stdio2)
573 use_browser = 0; 582 use_browser = 0;
574 else if (annotate.use_tui) 583 else if (annotate.use_tui)
575 use_browser = 1; 584 use_browser = 1;
@@ -578,7 +587,7 @@ int cmd_annotate(int argc, const char **argv)
578 587
579 setup_browser(true); 588 setup_browser(true);
580 589
581 if (use_browser == 1 && annotate.has_br_stack) { 590 if ((use_browser == 1 || annotate.use_stdio2) && annotate.has_br_stack) {
582 sort__mode = SORT_MODE__BRANCH; 591 sort__mode = SORT_MODE__BRANCH;
583 if (setup_sorting(annotate.session->evlist) < 0) 592 if (setup_sorting(annotate.session->evlist) < 0)
584 usage_with_options(annotate_usage, options); 593 usage_with_options(annotate_usage, options);
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 11ad73211538..98cf3e5380bc 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -1965,6 +1965,72 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
1965 return more; 1965 return more;
1966} 1966}
1967 1967
1968static void FILE__set_percent_color(void *fp __maybe_unused,
1969 double percent __maybe_unused,
1970 bool current __maybe_unused)
1971{
1972}
1973
1974static int FILE__set_jumps_percent_color(void *fp __maybe_unused,
1975 int nr __maybe_unused, bool current __maybe_unused)
1976{
1977 return 0;
1978}
1979
1980static int FILE__set_color(void *fp __maybe_unused, int color __maybe_unused)
1981{
1982 return 0;
1983}
1984
1985static void FILE__printf(void *fp, const char *fmt, ...)
1986{
1987 va_list args;
1988
1989 va_start(args, fmt);
1990 vfprintf(fp, fmt, args);
1991 va_end(args);
1992}
1993
1994static void FILE__write_graph(void *fp, int graph)
1995{
1996 const char *s;
1997 switch (graph) {
1998
1999 case DARROW_CHAR: s = "↓"; break;
2000 case UARROW_CHAR: s = "↑"; break;
2001 case LARROW_CHAR: s = "←"; break;
2002 case RARROW_CHAR: s = "→"; break;
2003 default: s = "?"; break;
2004 }
2005
2006 fputs(s, fp);
2007}
2008
2009int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp)
2010{
2011 struct annotation *notes = symbol__annotation(sym);
2012 struct annotation_write_ops ops = {
2013 .first_line = true,
2014 .obj = fp,
2015 .set_color = FILE__set_color,
2016 .set_percent_color = FILE__set_percent_color,
2017 .set_jumps_percent_color = FILE__set_jumps_percent_color,
2018 .printf = FILE__printf,
2019 .write_graph = FILE__write_graph,
2020 };
2021 struct annotation_line *al;
2022
2023 list_for_each_entry(al, &notes->src->source, node) {
2024 if (annotation_line__filter(al, notes))
2025 continue;
2026 annotation_line__write(al, notes, &ops);
2027 fputc('\n', fp);
2028 ops.first_line = false;
2029 }
2030
2031 return 0;
2032}
2033
1968void symbol__annotate_zero_histogram(struct symbol *sym, int evidx) 2034void symbol__annotate_zero_histogram(struct symbol *sym, int evidx)
1969{ 2035{
1970 struct annotation *notes = symbol__annotation(sym); 2036 struct annotation *notes = symbol__annotation(sym);
@@ -2165,6 +2231,32 @@ static void symbol__calc_lines(struct symbol *sym, struct map *map,
2165 annotation__calc_lines(notes, map, root, start); 2231 annotation__calc_lines(notes, map, root, start);
2166} 2232}
2167 2233
2234int symbol__tty_annotate2(struct symbol *sym, struct map *map,
2235 struct perf_evsel *evsel, bool print_lines,
2236 bool full_paths)
2237{
2238 struct dso *dso = map->dso;
2239 struct rb_root source_line = RB_ROOT;
2240 struct annotation_options opts = {
2241 .use_offset = true,
2242 };
2243
2244 if (symbol__annotate2(sym, map, evsel, &opts, NULL) < 0)
2245 return -1;
2246
2247 if (print_lines) {
2248 srcline_full_filename = full_paths;
2249 symbol__calc_lines(sym, map, &source_line);
2250 print_summary(&source_line, dso->long_name);
2251 }
2252
2253 symbol__annotate_fprintf2(sym, stdout);
2254
2255 annotated_source__purge(symbol__annotation(sym)->src);
2256
2257 return 0;
2258}
2259
2168int symbol__tty_annotate(struct symbol *sym, struct map *map, 2260int symbol__tty_annotate(struct symbol *sym, struct map *map,
2169 struct perf_evsel *evsel, bool print_lines, 2261 struct perf_evsel *evsel, bool print_lines,
2170 bool full_paths, int min_pcnt, int max_lines) 2262 bool full_paths, int min_pcnt, int max_lines)
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 165845de1243..cf32cbc87930 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -281,6 +281,7 @@ int symbol__strerror_disassemble(struct symbol *sym, struct map *map,
281int symbol__annotate_printf(struct symbol *sym, struct map *map, 281int symbol__annotate_printf(struct symbol *sym, struct map *map,
282 struct perf_evsel *evsel, bool full_paths, 282 struct perf_evsel *evsel, bool full_paths,
283 int min_pcnt, int max_lines, int context); 283 int min_pcnt, int max_lines, int context);
284int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp);
284void symbol__annotate_zero_histogram(struct symbol *sym, int evidx); 285void symbol__annotate_zero_histogram(struct symbol *sym, int evidx);
285void symbol__annotate_decay_histogram(struct symbol *sym, int evidx); 286void symbol__annotate_decay_histogram(struct symbol *sym, int evidx);
286void annotated_source__purge(struct annotated_source *as); 287void annotated_source__purge(struct annotated_source *as);
@@ -291,6 +292,10 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,
291 struct perf_evsel *evsel, bool print_lines, 292 struct perf_evsel *evsel, bool print_lines,
292 bool full_paths, int min_pcnt, int max_lines); 293 bool full_paths, int min_pcnt, int max_lines);
293 294
295int symbol__tty_annotate2(struct symbol *sym, struct map *map,
296 struct perf_evsel *evsel, bool print_lines,
297 bool full_paths);
298
294#ifdef HAVE_SLANG_SUPPORT 299#ifdef HAVE_SLANG_SUPPORT
295int symbol__tui_annotate(struct symbol *sym, struct map *map, 300int symbol__tui_annotate(struct symbol *sym, struct map *map,
296 struct perf_evsel *evsel, 301 struct perf_evsel *evsel,