diff options
Diffstat (limited to '')
-rw-r--r-- | tools/perf/ui/stdio/hist.c | 75 |
1 files changed, 51 insertions, 24 deletions
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c index 2ab2af4d4849..8c4c8925df2c 100644 --- a/tools/perf/ui/stdio/hist.c +++ b/tools/perf/ui/stdio/hist.c @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 +#include <limits.h> #include <stdio.h> #include <stdlib.h> #include <linux/string.h> @@ -24,6 +25,9 @@ static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin) int i; int ret = fprintf(fp, " "); + if (left_margin > USHRT_MAX) + left_margin = USHRT_MAX; + for (i = 0; i < left_margin; i++) ret += fprintf(fp, " "); @@ -639,45 +643,58 @@ static int hists__fprintf_hierarchy_headers(struct hists *hists, unsigned header_width = 0; struct perf_hpp_fmt *fmt; struct perf_hpp_list_node *fmt_node; + struct perf_hpp_list *hpp_list = hists->hpp_list; const char *sep = symbol_conf.field_sep; indent = hists->nr_hpp_node; - /* preserve max indent depth for column headers */ - print_hierarchy_indent(sep, indent, " ", fp); - /* the first hpp_list_node is for overhead columns */ fmt_node = list_first_entry(&hists->hpp_formats, struct perf_hpp_list_node, list); - perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) { - fmt->header(fmt, hpp, hists, 0, NULL); - fprintf(fp, "%s%s", hpp->buf, sep ?: " "); - } + for (int line = 0; line < hpp_list->nr_header_lines; line++) { + /* first # is displayed one level up */ + if (line) + fprintf(fp, "# "); - /* combine sort headers with ' / ' */ - first_node = true; - list_for_each_entry_continue(fmt_node, &hists->hpp_formats, list) { - if (!first_node) - header_width += fprintf(fp, " / "); - first_node = false; + /* preserve max indent depth for column headers */ + print_hierarchy_indent(sep, indent, " ", fp); - first_col = true; perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) { - if (perf_hpp__should_skip(fmt, hists)) - continue; + fmt->header(fmt, hpp, hists, line, NULL); + fprintf(fp, "%s%s", hpp->buf, sep ?: " "); + } - if (!first_col) - header_width += fprintf(fp, "+"); - first_col = false; + if (line < hpp_list->nr_header_lines - 1) + goto next_line; + + /* combine sort headers with ' / ' */ + first_node = true; + list_for_each_entry_continue(fmt_node, &hists->hpp_formats, list) { + if (!first_node) + header_width += fprintf(fp, " / "); + first_node = false; + + first_col = true; + perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) { + if (perf_hpp__should_skip(fmt, hists)) + continue; + + if (!first_col) + header_width += fprintf(fp, "+"); + first_col = false; - fmt->header(fmt, hpp, hists, 0, NULL); + fmt->header(fmt, hpp, hists, line, NULL); - header_width += fprintf(fp, "%s", strim(hpp->buf)); + header_width += fprintf(fp, "%s", strim(hpp->buf)); + } } + +next_line: + fprintf(fp, "\n"); } - fprintf(fp, "\n# "); + fprintf(fp, "# "); /* preserve max indent depth for initial dots */ print_hierarchy_indent(sep, indent, dots, fp); @@ -885,7 +902,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, } if (h->ms.map == NULL && verbose > 1) { - maps__fprintf(h->thread->maps, fp); + maps__fprintf(thread__maps(h->thread), fp); fprintf(fp, "%.10s end\n", graph_dotted_line); } } @@ -901,6 +918,7 @@ size_t events_stats__fprintf(struct events_stats *stats, FILE *fp) { int i; size_t ret = 0; + u32 total = stats->nr_events[0]; for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) { const char *name; @@ -908,8 +926,17 @@ size_t events_stats__fprintf(struct events_stats *stats, FILE *fp) name = perf_event__name(i); if (!strcmp(name, "UNKNOWN")) continue; + if (symbol_conf.skip_empty && !stats->nr_events[i]) + continue; - ret += fprintf(fp, "%16s events: %10d\n", name, stats->nr_events[i]); + if (i && total) { + ret += fprintf(fp, "%20s events: %10d (%4.1f%%)\n", + name, stats->nr_events[i], + 100.0 * stats->nr_events[i] / total); + } else { + ret += fprintf(fp, "%20s events: %10d\n", + name, stats->nr_events[i]); + } } return ret; |