]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
perf hist: Set levels in output_field_add()
authorNamhyung Kim <namhyung@kernel.org>
Mon, 31 Mar 2025 07:37:21 +0000 (00:37 -0700)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 25 Apr 2025 15:31:54 +0000 (12:31 -0300)
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>
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: Peter Zijlstra <peterz@infradead.org>
Link: https://lore.kernel.org/r/20250331073722.4695-4-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/builtin-c2c.c
tools/perf/util/sort.c
tools/perf/util/sort.h

index 5d5bb0f32334a97510a017641c2363286e73cb95..e2e257bcc461fbdb2798e39f9989e72886c06768 100644 (file)
@@ -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);
index c51049087e4ebb6cf5e4cd12bf73d07bf1a31e7e..594b75ca95bf72b264762961d82a1bf4e2048961 100644 (file)
@@ -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;
index 180d36a2bea355dab05d0ce0d2178f1dbd37923d..6e92ac62b9c80a0bdc9accea8285d70c730b4828 100644 (file)
@@ -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