Re: [PATCH 07/17] perf ui/stdio: Align column header for hierarchy output

From: Arnaldo Carvalho de Melo
Date: Wed Jan 20 2016 - 17:40:52 EST


Em Sun, Jan 17, 2016 at 01:03:07AM +0900, Namhyung Kim escreveu:
> The hierarchy output mode is to group entries so the existing columns
> won't fit to the new output. Treat all sort keys as a single column and
> separate headers by "/".
>
> # Overhead Command / Shared Object
> # ........... ................................
> #
> 15.11% swapper
> 14.97% [kernel.vmlinux]
> 0.09% [libahci]
> 0.05% [iwlwifi]
> ...
>
> Signed-off-by: Namhyung Kim <namhyung@xxxxxxxxxx>
> ---
> tools/perf/ui/stdio/hist.c | 107 +++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 107 insertions(+)
>
> diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
> index 0cd7c651a0e8..38279478a06d 100644
> --- a/tools/perf/ui/stdio/hist.c
> +++ b/tools/perf/ui/stdio/hist.c
> @@ -502,6 +502,108 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size,
> return ret;
> }
>
> +static int print_hierarchy_indent(const char *sep, int nr_sort,
> + const char *line, FILE *fp)
> +{
> + if (sep != NULL || nr_sort < 1)
> + return 0;
> +
> + return fprintf(fp, "%-.*s", (nr_sort - 1) * HIERARCHY_INDENT, line);
> +}
> +
> +static int print_hierarchy_header(struct hists *hists, struct perf_hpp *hpp,
> + const char *sep, FILE *fp)
> +{
> + bool first = true;
> + int nr_sort;
> + unsigned width = 0;
> + unsigned header_width = 0;
> + struct perf_hpp_fmt *fmt;
> + const char spaces[] = " "
> + " "
> + " ";
> + const char dots[] = "................................................."
> + "....................................................................."
> + ".....................................................................";
> +
> + nr_sort = perf_hpp__count_sort_keys();
> +
> + /* preserve max indent depth for column headers */
> + print_hierarchy_indent(sep, nr_sort, spaces, fp);
> +
> + perf_hpp__for_each_format(fmt) {
> + if (perf_hpp__is_sort_entry(fmt) || perf_hpp__is_dynamic_entry(fmt))
> + break;
> +
> + if (!first)
> + fprintf(fp, "%s", sep ?: " ");
> + else
> + first = false;
> +
> + fmt->header(fmt, hpp, hists_to_evsel(hists));
> + fprintf(fp, "%s", hpp->buf);

We already have code that prints dots or spaces according to a given
width, but in tools/perf/ui/stdio/hist.c hists__fprintf() it does it
using a fprintf loop, gack, would be better to settle in one way.

Can be done later, sure, processing as-is.

- Arnaldo

> + }
> +
> + /* combine sort headers with ' / ' */
> + first = true;
> + perf_hpp__for_each_format(fmt) {
> + if (!perf_hpp__is_sort_entry(fmt) && !perf_hpp__is_dynamic_entry(fmt))
> + continue;
> +
> + if (!first)
> + header_width += fprintf(fp, " / ");
> + else {
> + header_width += fprintf(fp, "%s", sep ?: " ");
> + first = false;
> + }
> +
> + fmt->header(fmt, hpp, hists_to_evsel(hists));
> + rtrim(hpp->buf);
> +
> + header_width += fprintf(fp, "%s", hpp->buf);
> + }
> +
> + /* preserve max indent depth for combined sort headers */
> + print_hierarchy_indent(sep, nr_sort, spaces, fp);
> +
> + fprintf(fp, "\n# ");
> +
> + /* preserve max indent depth for initial dots */
> + print_hierarchy_indent(sep, nr_sort, dots, fp);
> +
> + first = true;
> + perf_hpp__for_each_format(fmt) {
> + if (perf_hpp__is_sort_entry(fmt) || perf_hpp__is_dynamic_entry(fmt))
> + break;
> +
> + if (!first)
> + fprintf(fp, "%s", sep ?: " ");
> + else
> + first = false;
> +
> + width = fmt->width(fmt, hpp, hists_to_evsel(hists));
> + fprintf(fp, "%.*s", width, dots);
> + }
> +
> + perf_hpp__for_each_format(fmt) {
> + if (!perf_hpp__is_sort_entry(fmt) && !perf_hpp__is_dynamic_entry(fmt))
> + continue;
> +
> + width = fmt->width(fmt, hpp, hists_to_evsel(hists));
> + if (width > header_width)
> + header_width = width;
> + }
> +
> + fprintf(fp, "%s%-.*s", sep ?: " ", header_width, dots);
> +
> + /* preserve max indent depth for dots under sort headers */
> + print_hierarchy_indent(sep, nr_sort, dots, fp);
> +
> + fprintf(fp, "\n#\n");
> +
> + return 2;
> +}
> +
> size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
> int max_cols, float min_pcnt, FILE *fp)
> {
> @@ -533,6 +635,11 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
>
> fprintf(fp, "# ");
>
> + if (symbol_conf.report_hierarchy) {
> + nr_rows += print_hierarchy_header(hists, &dummy_hpp, sep, fp);
> + goto print_entries;
> + }
> +
> perf_hpp__for_each_format(fmt) {
> if (perf_hpp__should_skip(fmt, hists))
> continue;
> --
> 2.6.4