Commit 29e6392e authored by Namhyung Kim's avatar Namhyung Kim Committed by Arnaldo Carvalho de Melo
Browse files

perf hist: Support multi-line header



This is a preparation to support multi-line headers in 'perf mem report'.

Normal sort keys and output fields that don't have contents for multi-
line will print the header string at the last line only.

As we don't use multi-line headers normally, it should not have any
changes in the output.

Signed-off-by: default avatarNamhyung Kim <namhyung@kernel.org>
Tested-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Leo Yan <leo.yan@arm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ravi Bangoria <ravi.bangoria@amd.com>
Link: https://lore.kernel.org/r/20250430205548.789750-4-namhyung@kernel.org


Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 43a64469
Loading
Loading
Loading
Loading
+16 −8
Original line number Diff line number Diff line
@@ -1686,7 +1686,8 @@ hists_browser__scnprintf_headers(struct hist_browser *browser, char *buf,
	return ret;
}

static int hists_browser__scnprintf_hierarchy_headers(struct hist_browser *browser, char *buf, size_t size)
static int hists_browser__scnprintf_hierarchy_headers(struct hist_browser *browser,
						      char *buf, size_t size, int line)
{
	struct hists *hists = browser->hists;
	struct perf_hpp dummy_hpp = {
@@ -1712,7 +1713,7 @@ static int hists_browser__scnprintf_hierarchy_headers(struct hist_browser *brows
		if (column++ < browser->b.horiz_scroll)
			continue;

		ret = fmt->header(fmt, &dummy_hpp, hists, 0, NULL);
		ret = fmt->header(fmt, &dummy_hpp, hists, line, NULL);
		if (advance_hpp_check(&dummy_hpp, ret))
			break;

@@ -1723,6 +1724,9 @@ static int hists_browser__scnprintf_hierarchy_headers(struct hist_browser *brows
		first_node = false;
	}

	if (line < hists->hpp_list->nr_header_lines - 1)
		return ret;

	if (!first_node) {
		ret = scnprintf(dummy_hpp.buf, dummy_hpp.size, "%*s",
				indent * HIERARCHY_INDENT, "");
@@ -1753,7 +1757,7 @@ static int hists_browser__scnprintf_hierarchy_headers(struct hist_browser *brows
			}
			first_col = false;

			ret = fmt->header(fmt, &dummy_hpp, hists, 0, NULL);
			ret = fmt->header(fmt, &dummy_hpp, hists, line, NULL);
			dummy_hpp.buf[ret] = '\0';

			start = strim(dummy_hpp.buf);
@@ -1772,15 +1776,19 @@ static int hists_browser__scnprintf_hierarchy_headers(struct hist_browser *brows

static void hists_browser__hierarchy_headers(struct hist_browser *browser)
{
	struct perf_hpp_list *hpp_list = browser->hists->hpp_list;
	char headers[1024];
	int line;

	for (line = 0; line < hpp_list->nr_header_lines; line++) {
		hists_browser__scnprintf_hierarchy_headers(browser, headers,
						   sizeof(headers));
							   sizeof(headers), line);

	ui_browser__gotorc_title(&browser->b, 0, 0);
		ui_browser__gotorc_title(&browser->b, line, 0);
		ui_browser__set_color(&browser->b, HE_COLORSET_ROOT);
		ui_browser__write_nstring(&browser->b, headers, browser->b.width + 1);
	}
}

static void hists_browser__headers(struct hist_browser *browser)
{
+7 −2
Original line number Diff line number Diff line
@@ -321,11 +321,16 @@ static int hpp__width_fn(struct perf_hpp_fmt *fmt,
}

static int hpp__header_fn(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
			  struct hists *hists, int line __maybe_unused,
			  struct hists *hists, int line,
			  int *span __maybe_unused)
{
	int len = hpp__width_fn(fmt, hpp, hists);
	return scnprintf(hpp->buf, hpp->size, "%*s", len, fmt->name);
	const char *hdr = "";

	if (line == hists->hpp_list->nr_header_lines - 1)
		hdr = fmt->name;

	return scnprintf(hpp->buf, hpp->size, "%*s", len, hdr);
}

int hpp_color_scnprintf(struct perf_hpp *hpp, const char *fmt, ...)
+35 −22
Original line number Diff line number Diff line
@@ -643,22 +643,31 @@ 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);

	for (int line = 0; line < hpp_list->nr_header_lines; line++) {
		/* first # is displayed one level up */
		if (line)
			fprintf(fp, "# ");

		/* preserve max indent depth for column headers */
		print_hierarchy_indent(sep, indent, " ", fp);

		perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) {
		fmt->header(fmt, hpp, hists, 0, NULL);
			fmt->header(fmt, hpp, hists, line, NULL);
			fprintf(fp, "%s%s", hpp->buf, sep ?: "  ");
		}

		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) {
@@ -675,13 +684,17 @@ static int hists__fprintf_hierarchy_headers(struct hists *hists,
					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));
			}
		}

	fprintf(fp, "\n# ");
next_line:
		fprintf(fp, "\n");
	}

	fprintf(fp, "# ");

	/* preserve max indent depth for initial dots */
	print_hierarchy_indent(sep, indent, dots, fp);
+6 −2
Original line number Diff line number Diff line
@@ -2641,18 +2641,22 @@ void perf_hpp__reset_sort_width(struct perf_hpp_fmt *fmt, struct hists *hists)
}

static int __sort__hpp_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
			      struct hists *hists, int line __maybe_unused,
			      struct hists *hists, int line,
			      int *span __maybe_unused)
{
	struct hpp_sort_entry *hse;
	size_t len = fmt->user_len;
	const char *hdr = "";

	if (line == hists->hpp_list->nr_header_lines - 1)
		hdr = fmt->name;

	hse = container_of(fmt, struct hpp_sort_entry, hpp);

	if (!len)
		len = hists__col_len(hists, hse->se->se_width_idx);

	return scnprintf(hpp->buf, hpp->size, "%-*.*s", len, len, fmt->name);
	return scnprintf(hpp->buf, hpp->size, "%-*.*s", len, len, hdr);
}

static int __sort__hpp_width(struct perf_hpp_fmt *fmt,