perf ftrace latency: allow to hide empty buckets
authorGabriele Monaco <gmonaco@redhat.com>
Fri, 7 Feb 2025 08:04:45 +0000 (09:04 +0100)
committerNamhyung Kim <namhyung@kernel.org>
Wed, 26 Feb 2025 21:48:02 +0000 (13:48 -0800)
Especially while using several buckets, it isn't uncommon to have some
of them empty and reading the histogram may be a bit more complex:

  # perf ftrace latency -a -T mutex_lock --bucket-range 5 --max-latency 200
  #   DURATION     |  COUNT | GRAPH                                  |
       0 -    5 us |  14816 | ###################################### |
       5 -   10 us |   1228 | ###                                    |
      10 -   15 us |    438 | #                                      |
      15 -   20 us |    106 |                                        |
      20 -   25 us |     21 |                                        |
      25 -   30 us |     11 |                                        |
      30 -   35 us |      1 |                                        |
      35 -   40 us |      2 |                                        |
      40 -   45 us |      4 |                                        |
      45 -   50 us |      0 |                                        |
      50 -   55 us |      1 |                                        |
      55 -   60 us |      0 |                                        |
      60 -   65 us |      1 |                                        |
      65 -   70 us |      1 |                                        |
      70 -   75 us |      1 |                                        |
      75 -   80 us |      2 |                                        |
      80 -   85 us |      0 |                                        |
      85 -   90 us |      1 |                                        |
      90 -   95 us |      0 |                                        |
      95 -  100 us |      1 |                                        |
     100 -  105 us |      0 |                                        |
     105 -  110 us |      0 |                                        |
     110 -  115 us |      0 |                                        |
     115 -  120 us |      0 |                                        |
     120 -  125 us |      1 |                                        |
     125 -  130 us |      0 |                                        |
     130 -  135 us |      0 |                                        |
     135 -  140 us |      1 |                                        |
     140 -  145 us |      0 |                                        |
     145 -  150 us |      0 |                                        |
     150 -  155 us |      0 |                                        |
     155 -  160 us |      0 |                                        |
     160 -  165 us |      0 |                                        |
     165 -  170 us |      0 |                                        |
     170 -  175 us |      0 |                                        |
     175 -  180 us |      0 |                                        |
     180 -  185 us |      0 |                                        |
     185 -  190 us |      0 |                                        |
     190 -  195 us |      0 |                                        |
     195 -  200 us |      0 |                                        |
     200 -  ... us |      2 |                                        |

Allow the optional flag --hide-empty to remove buckets with no element
and produce a more compact graph. This feature could be misleading since
there is no clear indication for missing buckets, for this reason it's
disabled by default.

  # perf ftrace latency -a -T mutex_lock --bucket-range 5 --max-latency --hide-empty 200
  #   DURATION     |  COUNT | GRAPH                                  |
       0 -    5 us |  14816 | ###################################### |
       5 -   10 us |   1228 | ###                                    |
      10 -   15 us |    438 | #                                      |
      15 -   20 us |    106 |                                        |
      20 -   25 us |     21 |                                        |
      25 -   30 us |     11 |                                        |
      30 -   35 us |      1 |                                        |
      35 -   40 us |      2 |                                        |
      40 -   45 us |      4 |                                        |
      50 -   55 us |      1 |                                        |
      60 -   65 us |      1 |                                        |
      65 -   70 us |      1 |                                        |
      70 -   75 us |      1 |                                        |
      75 -   80 us |      2 |                                        |
      85 -   90 us |      1 |                                        |
      95 -  100 us |      1 |                                        |
     120 -  125 us |      1 |                                        |
     135 -  140 us |      1 |                                        |
     200 -  ... us |      2 |                                        |

Signed-off-by: Gabriele Monaco <gmonaco@redhat.com>
Link: https://lore.kernel.org/r/20250207080446.77630-2-gmonaco@redhat.com
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
tools/perf/builtin-ftrace.c
tools/perf/util/ftrace.h

index 4f76094ea06d40c7ad63f960161f84993e28f693..7caa18d5ffc382381ced75e34b505a300c5728a1 100644 (file)
@@ -841,14 +841,17 @@ static void display_histogram(struct perf_ftrace *ftrace, int buckets[])
 
        bar_len = buckets[0] * bar_total / total;
 
-       printf("  %4d - %4d %s | %10d | %.*s%*s |\n",
-              0, min_latency ?: 1, use_nsec ? "ns" : "us",
-              buckets[0], bar_len, bar, bar_total - bar_len, "");
+       if (!ftrace->hide_empty || buckets[0])
+               printf("  %4d - %4d %s | %10d | %.*s%*s |\n",
+                      0, min_latency ?: 1, use_nsec ? "ns" : "us",
+                      buckets[0], bar_len, bar, bar_total - bar_len, "");
 
        for (i = 1; i < bucket_num - 1; i++) {
                unsigned int start, stop;
                const char *unit = use_nsec ? "ns" : "us";
 
+               if (ftrace->hide_empty && !buckets[i])
+                       continue;
                if (!ftrace->bucket_range) {
                        start = (1 << (i - 1));
                        stop  = 1 << i;
@@ -884,6 +887,8 @@ print_bucket_info:
        }
 
        bar_len = buckets[bucket_num - 1] * bar_total / total;
+       if (ftrace->hide_empty && !buckets[bucket_num - 1])
+               goto print_stats;
        if (!ftrace->bucket_range) {
                printf("  %4d - %-4s %s", 1, "...", use_nsec ? "ms" : "s ");
        } else {
@@ -902,6 +907,7 @@ print_bucket_info:
        printf(" | %10d | %.*s%*s |\n", buckets[bucket_num - 1],
               bar_len, bar, bar_total - bar_len, "");
 
+print_stats:
        printf("\n# statistics  (in %s)\n", ftrace->use_nsec ? "nsec" : "usec");
        printf("  total time: %20.0f\n", latency_stats.mean * latency_stats.n);
        printf("    avg time: %20.0f\n", latency_stats.mean);
@@ -1645,6 +1651,8 @@ int cmd_ftrace(int argc, const char **argv)
                    "Minimum latency (1st bucket). Works only with --bucket-range."),
        OPT_UINTEGER(0, "max-latency", &ftrace.max_latency,
                    "Maximum latency (last bucket). Works only with --bucket-range."),
+       OPT_BOOLEAN(0, "hide-empty", &ftrace.hide_empty,
+                   "Hide empty buckets in the histogram"),
        OPT_PARENT(common_options),
        };
        const struct option profile_options[] = {
index 395f97b203ead4fbf03eca490201e570990acc21..a9bc47da83a56cd685966ad8cbd43bf6c29f3776 100644 (file)
@@ -25,6 +25,7 @@ struct perf_ftrace {
        unsigned int            min_latency;
        unsigned int            max_latency;
        unsigned int            bucket_num;
+       bool                    hide_empty;
        int                     graph_depth;
        int                     func_stack_trace;
        int                     func_irq_info;