linux-perf-users.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] perf report: Support custom output fields in hierarchy mode
@ 2025-03-31  7:37 Namhyung Kim
  2025-03-31  7:37 ` [PATCH 1/4] perf hist: Remove formats in hierarchy when cancel children Namhyung Kim
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Namhyung Kim @ 2025-03-31  7:37 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo, Ian Rogers, Kan Liang
  Cc: Jiri Olsa, Adrian Hunter, Peter Zijlstra, Ingo Molnar, LKML,
	linux-perf-users

Hello,

This is to remove arbitrary restrictions in the hierarchy mode.

The -F/--fields option is to specify output fields and sort keys in perf
report exactly what users want.  It was not allowed in the hierarchy mode
because it missed to handle the field correctly.

This patchset addresses that problem and allows the option.  It'd make
the output more flexible.  For example, this is possible:

  $ perf report -F overhead,comm,dso -H

Thanks,
Namhyung


Namhyung Kim (4):
  perf hist: Remove formats in hierarchy when cancel children
  perf hist: Remove formats in hierarchy when cancel latency
  perf hist: Set levels in output_field_add()
  perf hist: Allow custom output fields in hierarchy mode

 tools/perf/builtin-c2c.c    |  3 ++-
 tools/perf/builtin-report.c | 16 ++++++----------
 tools/perf/builtin-top.c    |  2 +-
 tools/perf/ui/hist.c        | 35 +++++++++++++++++++++++++++++++++--
 tools/perf/util/hist.h      |  4 ++--
 tools/perf/util/sort.c      | 36 +++++++++++++++++++++++-------------
 tools/perf/util/sort.h      |  2 +-
 7 files changed, 68 insertions(+), 30 deletions(-)


base-commit: 35d13f841a3d8159ef20d5e32a9ed3faa27875bc
-- 
2.49.0


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/4] perf hist: Remove formats in hierarchy when cancel children
  2025-03-31  7:37 [PATCH 0/4] perf report: Support custom output fields in hierarchy mode Namhyung Kim
@ 2025-03-31  7:37 ` Namhyung Kim
  2025-03-31  7:37 ` [PATCH 2/4] perf hist: Remove formats in hierarchy when cancel latency Namhyung Kim
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Namhyung Kim @ 2025-03-31  7:37 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo, Ian Rogers, Kan Liang
  Cc: Jiri Olsa, Adrian Hunter, Peter Zijlstra, Ingo Molnar, LKML,
	linux-perf-users

This is to support hierarchy options with custom output fields.
Currently perf_hpp__cancel_cumulate() only removes accumulated
overhead and latency fields from the global perf_hpp_list.

This is not used in the hierarchy mode because each evsel's hist
has its own separate hpp_list.  So it needs to remove the fields
from the lists too.  Pass evlist to the function so that it can
iterate the evsels.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/builtin-report.c |  2 +-
 tools/perf/builtin-top.c    |  2 +-
 tools/perf/ui/hist.c        | 20 +++++++++++++++++++-
 tools/perf/util/hist.h      |  2 +-
 4 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index b030ce72e13ea8d1..c9138e1379808097 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -413,7 +413,7 @@ static int report__setup_sample_type(struct report *rep)
 		/* Silently ignore if callchain is missing */
 		if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) {
 			symbol_conf.cumulate_callchain = false;
-			perf_hpp__cancel_cumulate();
+			perf_hpp__cancel_cumulate(session->evlist);
 		}
 	}
 
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 1061f4eebc3f6414..f9f31391bddba074 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -1790,7 +1790,7 @@ int cmd_top(int argc, const char **argv)
 
 	if (!callchain_param.enabled) {
 		symbol_conf.cumulate_callchain = false;
-		perf_hpp__cancel_cumulate();
+		perf_hpp__cancel_cumulate(top.evlist);
 	}
 
 	if (symbol_conf.cumulate_callchain && !callchain_param.order_set)
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index ae3b7fe1dadc8f22..1d3f944ed35ed152 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -699,9 +699,10 @@ static void perf_hpp__column_unregister(struct perf_hpp_fmt *format)
 	fmt_free(format);
 }
 
-void perf_hpp__cancel_cumulate(void)
+void perf_hpp__cancel_cumulate(struct evlist *evlist)
 {
 	struct perf_hpp_fmt *fmt, *acc, *ovh, *acc_lat, *tmp;
+	struct evsel *evsel;
 
 	if (is_strict_order(field_order))
 		return;
@@ -719,6 +720,23 @@ void perf_hpp__cancel_cumulate(void)
 		if (fmt_equal(ovh, fmt))
 			fmt->name = "Overhead";
 	}
+
+	evlist__for_each_entry(evlist, evsel) {
+		struct hists *hists = evsel__hists(evsel);
+		struct perf_hpp_list_node *node;
+
+		list_for_each_entry(node, &hists->hpp_formats, list) {
+			perf_hpp_list__for_each_format_safe(&node->hpp, fmt, tmp) {
+				if (fmt_equal(acc, fmt) || fmt_equal(acc_lat, fmt)) {
+					perf_hpp__column_unregister(fmt);
+					continue;
+				}
+
+				if (fmt_equal(ovh, fmt))
+					fmt->name = "Overhead";
+			}
+		}
+	}
 }
 
 void perf_hpp__cancel_latency(void)
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 317d06cca8b88e3e..8cc94928fcb35a5b 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -581,7 +581,7 @@ enum {
 };
 
 void perf_hpp__init(void);
-void perf_hpp__cancel_cumulate(void);
+void perf_hpp__cancel_cumulate(struct evlist *evlist);
 void perf_hpp__cancel_latency(void);
 void perf_hpp__setup_output_field(struct perf_hpp_list *list);
 void perf_hpp__reset_output_field(struct perf_hpp_list *list);
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/4] perf hist: Remove formats in hierarchy when cancel latency
  2025-03-31  7:37 [PATCH 0/4] perf report: Support custom output fields in hierarchy mode Namhyung Kim
  2025-03-31  7:37 ` [PATCH 1/4] perf hist: Remove formats in hierarchy when cancel children Namhyung Kim
@ 2025-03-31  7:37 ` Namhyung Kim
  2025-03-31  7:37 ` [PATCH 3/4] perf hist: Set levels in output_field_add() Namhyung Kim
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Namhyung Kim @ 2025-03-31  7:37 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo, Ian Rogers, Kan Liang
  Cc: Jiri Olsa, Adrian Hunter, Peter Zijlstra, Ingo Molnar, LKML,
	linux-perf-users

Likewise, it should remove latency output fields in hierarchy list.
Pass evlist to perf_hpp__cancel_latency() to handle them properly.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/builtin-report.c |  2 +-
 tools/perf/ui/hist.c        | 15 ++++++++++++++-
 tools/perf/util/hist.h      |  2 +-
 3 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index c9138e1379808097..c207aaed7ae5fc2b 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -1088,7 +1088,7 @@ static int __cmd_report(struct report *rep)
 	/* Don't show Latency column for non-parallel profiles by default. */
 	if (!symbol_conf.prefer_latency && rep->total_samples &&
 		rep->singlethreaded_samples * 100 / rep->total_samples >= 99)
-		perf_hpp__cancel_latency();
+		perf_hpp__cancel_latency(session->evlist);
 
 	evlist__check_mem_load_aux(session->evlist);
 
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 1d3f944ed35ed152..3ffce69fc823e0bf 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -739,9 +739,10 @@ void perf_hpp__cancel_cumulate(struct evlist *evlist)
 	}
 }
 
-void perf_hpp__cancel_latency(void)
+void perf_hpp__cancel_latency(struct evlist *evlist)
 {
 	struct perf_hpp_fmt *fmt, *lat, *acc, *tmp;
+	struct evsel *evsel;
 
 	if (is_strict_order(field_order))
 		return;
@@ -755,6 +756,18 @@ void perf_hpp__cancel_latency(void)
 		if (fmt_equal(lat, fmt) || fmt_equal(acc, fmt))
 			perf_hpp__column_unregister(fmt);
 	}
+
+	evlist__for_each_entry(evlist, evsel) {
+		struct hists *hists = evsel__hists(evsel);
+		struct perf_hpp_list_node *node;
+
+		list_for_each_entry(node, &hists->hpp_formats, list) {
+			perf_hpp_list__for_each_format_safe(&node->hpp, fmt, tmp) {
+				if (fmt_equal(lat, fmt) || fmt_equal(acc, fmt))
+					perf_hpp__column_unregister(fmt);
+			}
+		}
+	}
 }
 
 void perf_hpp__setup_output_field(struct perf_hpp_list *list)
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 8cc94928fcb35a5b..76efd8952507a561 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -582,7 +582,7 @@ enum {
 
 void perf_hpp__init(void);
 void perf_hpp__cancel_cumulate(struct evlist *evlist);
-void perf_hpp__cancel_latency(void);
+void perf_hpp__cancel_latency(struct evlist *evlist);
 void perf_hpp__setup_output_field(struct perf_hpp_list *list);
 void perf_hpp__reset_output_field(struct perf_hpp_list *list);
 void perf_hpp__append_sort_keys(struct perf_hpp_list *list);
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 3/4] perf hist: Set levels in output_field_add()
  2025-03-31  7:37 [PATCH 0/4] perf report: Support custom output fields in hierarchy mode Namhyung Kim
  2025-03-31  7:37 ` [PATCH 1/4] perf hist: Remove formats in hierarchy when cancel children Namhyung Kim
  2025-03-31  7:37 ` [PATCH 2/4] perf hist: Remove formats in hierarchy when cancel latency Namhyung Kim
@ 2025-03-31  7:37 ` Namhyung Kim
  2025-03-31  7:37 ` [PATCH 4/4] perf hist: Allow custom output fields in hierarchy mode Namhyung Kim
  2025-04-23 20:46 ` [PATCH 0/4] perf report: Support " Arnaldo Carvalho de Melo
  4 siblings, 0 replies; 6+ messages in thread
From: Namhyung Kim @ 2025-03-31  7:37 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo, Ian Rogers, Kan Liang
  Cc: Jiri Olsa, Adrian Hunter, Peter Zijlstra, Ingo Molnar, LKML,
	linux-perf-users

It turns out that the output fields didn't consider the hierarchy mode
and put all the fields in the same level.  To support hierarchy, each
non-output field should be in a separate level.  Pass a pointer to level
to output_field_add() and make it increase the level when it sees non-
output fields.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/builtin-c2c.c |  3 ++-
 tools/perf/util/sort.c   | 36 +++++++++++++++++++++++-------------
 tools/perf/util/sort.h   |  2 +-
 3 files changed, 26 insertions(+), 15 deletions(-)

diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c
index 5d5bb0f32334a975..e2e257bcc461fbdb 100644
--- a/tools/perf/builtin-c2c.c
+++ b/tools/perf/builtin-c2c.c
@@ -1969,10 +1969,11 @@ static struct c2c_fmt *get_format(const char *name)
 static int c2c_hists__init_output(struct perf_hpp_list *hpp_list, char *name)
 {
 	struct c2c_fmt *c2c_fmt = get_format(name);
+	int level = 0;
 
 	if (!c2c_fmt) {
 		reset_dimensions();
-		return output_field_add(hpp_list, name);
+		return output_field_add(hpp_list, name, &level);
 	}
 
 	perf_hpp_list__column_register(hpp_list, &c2c_fmt->fmt);
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index c51049087e4ebb6c..594b75ca95bf72b2 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -2884,9 +2884,10 @@ static int __sort_dimension__add_hpp_sort(struct sort_dimension *sd,
 }
 
 static int __sort_dimension__add_hpp_output(struct sort_dimension *sd,
-					    struct perf_hpp_list *list)
+					    struct perf_hpp_list *list,
+					    int level)
 {
-	struct hpp_sort_entry *hse = __sort_dimension__alloc_hpp(sd, 0);
+	struct hpp_sort_entry *hse = __sort_dimension__alloc_hpp(sd, level);
 
 	if (hse == NULL)
 		return -1;
@@ -3495,12 +3496,13 @@ static int __hpp_dimension__add(struct hpp_dimension *hd,
 }
 
 static int __sort_dimension__add_output(struct perf_hpp_list *list,
-					struct sort_dimension *sd)
+					struct sort_dimension *sd,
+					int level)
 {
 	if (sd->taken)
 		return 0;
 
-	if (__sort_dimension__add_hpp_output(sd, list) < 0)
+	if (__sort_dimension__add_hpp_output(sd, list, level) < 0)
 		return -1;
 
 	sd->taken = 1;
@@ -3508,14 +3510,15 @@ static int __sort_dimension__add_output(struct perf_hpp_list *list,
 }
 
 static int __hpp_dimension__add_output(struct perf_hpp_list *list,
-				       struct hpp_dimension *hd)
+				       struct hpp_dimension *hd,
+				       int level)
 {
 	struct perf_hpp_fmt *fmt;
 
 	if (hd->taken)
 		return 0;
 
-	fmt = __hpp_dimension__alloc_hpp(hd, 0);
+	fmt = __hpp_dimension__alloc_hpp(hd, level);
 	if (!fmt)
 		return -1;
 
@@ -3532,7 +3535,7 @@ int hpp_dimension__add_output(unsigned col, bool implicit)
 	hd = &hpp_sort_dimensions[col];
 	if (implicit && !hd->was_taken)
 		return 0;
-	return __hpp_dimension__add_output(&perf_hpp_list, hd);
+	return __hpp_dimension__add_output(&perf_hpp_list, hd, /*level=*/0);
 }
 
 int sort_dimension__add(struct perf_hpp_list *list, const char *tok,
@@ -4000,7 +4003,7 @@ void sort__setup_elide(FILE *output)
 	}
 }
 
-int output_field_add(struct perf_hpp_list *list, const char *tok)
+int output_field_add(struct perf_hpp_list *list, const char *tok, int *level)
 {
 	unsigned int i;
 
@@ -4013,16 +4016,22 @@ int output_field_add(struct perf_hpp_list *list, const char *tok)
 		if (!strcasecmp(tok, "weight"))
 			ui__warning("--fields weight shows the average value unlike in the --sort key.\n");
 
-		return __hpp_dimension__add_output(list, hd);
+		return __hpp_dimension__add_output(list, hd, *level);
 	}
 
+	/*
+	 * A non-output field will increase level so that it can be in a
+	 * different hierarchy.
+	 */
+	(*level)++;
+
 	for (i = 0; i < ARRAY_SIZE(common_sort_dimensions); i++) {
 		struct sort_dimension *sd = &common_sort_dimensions[i];
 
 		if (!sd->name || strncasecmp(tok, sd->name, strlen(tok)))
 			continue;
 
-		return __sort_dimension__add_output(list, sd);
+		return __sort_dimension__add_output(list, sd, *level);
 	}
 
 	for (i = 0; i < ARRAY_SIZE(bstack_sort_dimensions); i++) {
@@ -4034,7 +4043,7 @@ int output_field_add(struct perf_hpp_list *list, const char *tok)
 		if (sort__mode != SORT_MODE__BRANCH)
 			return -EINVAL;
 
-		return __sort_dimension__add_output(list, sd);
+		return __sort_dimension__add_output(list, sd, *level);
 	}
 
 	for (i = 0; i < ARRAY_SIZE(memory_sort_dimensions); i++) {
@@ -4046,7 +4055,7 @@ int output_field_add(struct perf_hpp_list *list, const char *tok)
 		if (sort__mode != SORT_MODE__MEMORY)
 			return -EINVAL;
 
-		return __sort_dimension__add_output(list, sd);
+		return __sort_dimension__add_output(list, sd, *level);
 	}
 
 	return -ESRCH;
@@ -4056,10 +4065,11 @@ static int setup_output_list(struct perf_hpp_list *list, char *str)
 {
 	char *tmp, *tok;
 	int ret = 0;
+	int level = 0;
 
 	for (tok = strtok_r(str, ", ", &tmp);
 			tok; tok = strtok_r(NULL, ", ", &tmp)) {
-		ret = output_field_add(list, tok);
+		ret = output_field_add(list, tok, &level);
 		if (ret == -EINVAL) {
 			ui__error("Invalid --fields key: `%s'", tok);
 			break;
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 180d36a2bea355da..6e92ac62b9c80a0b 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -146,7 +146,7 @@ void reset_dimensions(void);
 int sort_dimension__add(struct perf_hpp_list *list, const char *tok,
 			struct evlist *evlist,
 			int level);
-int output_field_add(struct perf_hpp_list *list, const char *tok);
+int output_field_add(struct perf_hpp_list *list, const char *tok, int *level);
 int64_t
 sort__iaddr_cmp(struct hist_entry *left, struct hist_entry *right);
 int64_t
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 4/4] perf hist: Allow custom output fields in hierarchy mode
  2025-03-31  7:37 [PATCH 0/4] perf report: Support custom output fields in hierarchy mode Namhyung Kim
                   ` (2 preceding siblings ...)
  2025-03-31  7:37 ` [PATCH 3/4] perf hist: Set levels in output_field_add() Namhyung Kim
@ 2025-03-31  7:37 ` Namhyung Kim
  2025-04-23 20:46 ` [PATCH 0/4] perf report: Support " Arnaldo Carvalho de Melo
  4 siblings, 0 replies; 6+ messages in thread
From: Namhyung Kim @ 2025-03-31  7:37 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo, Ian Rogers, Kan Liang
  Cc: Jiri Olsa, Adrian Hunter, Peter Zijlstra, Ingo Molnar, LKML,
	linux-perf-users

Now it can handle multiple output fields and sort keys in separate
levels, so it should be ok to use it in the hierarchy mode.  This
allows fully customized output format.

  $ perf report -F latency,comm,parallelism -H --stdio
  ...
  #     Latency  Command / Parallelism
  # ...........  .....................
  #
      31.84%     cc1
         29.96%     5
          1.24%     4
          0.37%     6
          0.26%     3
          0.02%     2
      24.68%     as
         22.39%     5
          1.12%     2
          0.98%     4
          0.12%     3
          0.07%     6
          ...

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/builtin-report.c | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index c207aaed7ae5fc2b..f0299c7ee0254a37 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -1672,14 +1672,10 @@ int cmd_report(int argc, const char **argv)
 	}
 
 	if (symbol_conf.report_hierarchy) {
-		/* disable incompatible options */
-		if (field_order) {
-			pr_err("Error: --hierarchy and --fields options cannot be used together\n");
-			parse_options_usage(report_usage, options, "F", 1);
-			parse_options_usage(NULL, options, "hierarchy", 0);
-			goto error;
-		}
-
+		/*
+		 * The hist entries in hierarchy are added during the collpase
+		 * phase.  Let's enable it even if no sort keys require it.
+		 */
 		perf_hpp_list.need_collapse = true;
 	}
 
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 0/4] perf report: Support custom output fields in hierarchy mode
  2025-03-31  7:37 [PATCH 0/4] perf report: Support custom output fields in hierarchy mode Namhyung Kim
                   ` (3 preceding siblings ...)
  2025-03-31  7:37 ` [PATCH 4/4] perf hist: Allow custom output fields in hierarchy mode Namhyung Kim
@ 2025-04-23 20:46 ` Arnaldo Carvalho de Melo
  4 siblings, 0 replies; 6+ messages in thread
From: Arnaldo Carvalho de Melo @ 2025-04-23 20:46 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Ian Rogers, Kan Liang, Jiri Olsa, Adrian Hunter, Peter Zijlstra,
	Ingo Molnar, LKML, linux-perf-users

On Mon, Mar 31, 2025 at 12:37:18AM -0700, Namhyung Kim wrote:
> Hello,
> 
> This is to remove arbitrary restrictions in the hierarchy mode.
> 
> The -F/--fields option is to specify output fields and sort keys in perf
> report exactly what users want.  It was not allowed in the hierarchy mode
> because it missed to handle the field correctly.
> 
> This patchset addresses that problem and allows the option.  It'd make
> the output more flexible.  For example, this is possible:
> 
>   $ perf report -F overhead,comm,dso -H

Thanks, tested and applied to perf-tools-next.

- Arnaldo

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2025-04-23 20:46 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-03-31  7:37 [PATCH 0/4] perf report: Support custom output fields in hierarchy mode Namhyung Kim
2025-03-31  7:37 ` [PATCH 1/4] perf hist: Remove formats in hierarchy when cancel children Namhyung Kim
2025-03-31  7:37 ` [PATCH 2/4] perf hist: Remove formats in hierarchy when cancel latency Namhyung Kim
2025-03-31  7:37 ` [PATCH 3/4] perf hist: Set levels in output_field_add() Namhyung Kim
2025-03-31  7:37 ` [PATCH 4/4] perf hist: Allow custom output fields in hierarchy mode Namhyung Kim
2025-04-23 20:46 ` [PATCH 0/4] perf report: Support " Arnaldo Carvalho de Melo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).