]> www.infradead.org Git - linux.git/commitdiff
perf stat: Change color to threshold in print_metric
authorIan Rogers <irogers@google.com>
Thu, 17 Oct 2024 17:53:54 +0000 (10:53 -0700)
committerNamhyung Kim <namhyung@kernel.org>
Thu, 17 Oct 2024 19:44:26 +0000 (12:44 -0700)
Colors don't mean things in CSV and JSON output, switch to a threshold
enum value that the standard output can convert to a color. Updating
the CSV and JSON output will be later changes.

Signed-off-by: Ian Rogers <irogers@google.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: Yicong Yang <yangyicong@hisilicon.com>
Cc: Weilin Wang <weilin.wang@intel.com>
Cc: Will Deacon <will@kernel.org>
Cc: James Clark <james.clark@linaro.org>
Cc: Mike Leach <mike.leach@linaro.org>
Cc: Leo Yan <leo.yan@linux.dev>
Cc: Sumanth Korikkar <sumanthk@linux.ibm.com>
Cc: Thomas Richter <tmricht@linux.ibm.com>
Cc: Tim Chen <tim.c.chen@linux.intel.com>
Cc: John Garry <john.g.garry@oracle.com>
Link: https://lore.kernel.org/r/20241017175356.783793-6-irogers@google.com
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
tools/perf/arch/x86/util/iostat.c
tools/perf/builtin-script.c
tools/perf/util/stat-display.c
tools/perf/util/stat-shadow.c
tools/perf/util/stat.h

index df7b5dfcc26a51f30d5485992d78637b9cba1bf3..366b44d0bb7e59ddca67bf9b5428fb25de54c294 100644 (file)
@@ -444,7 +444,7 @@ void iostat_print_metric(struct perf_stat_config *config, struct evsel *evsel,
                iostat_value = (count->val - prev_count_val) /
                               ((double) count->run / count->ena);
        }
-       out->print_metric(config, out->ctx, NULL, "%8.0f", iostat_metric,
+       out->print_metric(config, out->ctx, METRIC_THRESHOLD_UNKNOWN, "%8.0f", iostat_metric,
                          iostat_value / (256 * 1024));
 }
 
index a644787fa9e1dc257f329c29cb94faa6056e0e1e..8c5d5cecfba489ce79537c0d78086b47f6bc54c0 100644 (file)
@@ -2136,11 +2136,11 @@ struct metric_ctx {
 };
 
 static void script_print_metric(struct perf_stat_config *config __maybe_unused,
-                               void *ctx, const char *color,
-                               const char *fmt,
-                               const char *unit, double val)
+                               void *ctx, enum metric_threshold_classify thresh,
+                               const char *fmt, const char *unit, double val)
 {
        struct metric_ctx *mctx = ctx;
+       const char *color = metric_threshold_classify__color(thresh);
 
        if (!fmt)
                return;
index c6d33010ed22a406d86d0739c6ff27a28494246e..5974aaead95f9b2b9ef7270223d971e424817864 100644 (file)
@@ -73,6 +73,19 @@ static const char *aggr_header_std[] = {
        [AGGR_GLOBAL]   =       ""
 };
 
+const char *metric_threshold_classify__color(enum metric_threshold_classify thresh)
+{
+       const char * const colors[] = {
+               "", /* unknown */
+               PERF_COLOR_RED,     /* bad */
+               PERF_COLOR_MAGENTA, /* nearly bad */
+               PERF_COLOR_YELLOW,  /* less good */
+               PERF_COLOR_GREEN,   /* good */
+       };
+       static_assert(ARRAY_SIZE(colors) - 1  == METRIC_THRESHOLD_GOOD, "missing enum value");
+       return colors[thresh];
+}
+
 static void print_running_std(struct perf_stat_config *config, u64 run, u64 ena)
 {
        if (run != ena)
@@ -405,13 +418,14 @@ static void do_new_line_std(struct perf_stat_config *config,
 }
 
 static void print_metric_std(struct perf_stat_config *config,
-                            void *ctx, const char *color, const char *fmt,
-                            const char *unit, double val)
+                            void *ctx, enum metric_threshold_classify thresh,
+                            const char *fmt, const char *unit, double val)
 {
        struct outstate *os = ctx;
        FILE *out = os->fh;
        int n;
        bool newline = os->newline;
+       const char *color = metric_threshold_classify__color(thresh);
 
        os->newline = false;
 
@@ -443,7 +457,7 @@ static void new_line_csv(struct perf_stat_config *config, void *ctx)
 
 static void print_metric_csv(struct perf_stat_config *config __maybe_unused,
                             void *ctx,
-                            const char *color __maybe_unused,
+                            enum metric_threshold_classify thresh __maybe_unused,
                             const char *fmt, const char *unit, double val)
 {
        struct outstate *os = ctx;
@@ -464,7 +478,7 @@ static void print_metric_csv(struct perf_stat_config *config __maybe_unused,
 
 static void print_metric_json(struct perf_stat_config *config __maybe_unused,
                             void *ctx,
-                            const char *color __maybe_unused,
+                            enum metric_threshold_classify thresh __maybe_unused,
                             const char *fmt __maybe_unused,
                             const char *unit, double val)
 {
@@ -559,13 +573,14 @@ static const char *fixunit(char *buf, struct evsel *evsel,
 }
 
 static void print_metric_only(struct perf_stat_config *config,
-                             void *ctx, const char *color, const char *fmt,
-                             const char *unit, double val)
+                             void *ctx, enum metric_threshold_classify thresh,
+                             const char *fmt, const char *unit, double val)
 {
        struct outstate *os = ctx;
        FILE *out = os->fh;
        char buf[1024], str[1024];
        unsigned mlen = config->metric_only_len;
+       const char *color = metric_threshold_classify__color(thresh);
 
        if (!valid_only_metric(unit))
                return;
@@ -582,7 +597,8 @@ static void print_metric_only(struct perf_stat_config *config,
 }
 
 static void print_metric_only_csv(struct perf_stat_config *config __maybe_unused,
-                                 void *ctx, const char *color __maybe_unused,
+                                 void *ctx,
+                                 enum metric_threshold_classify thresh __maybe_unused,
                                  const char *fmt,
                                  const char *unit, double val)
 {
@@ -604,7 +620,8 @@ static void print_metric_only_csv(struct perf_stat_config *config __maybe_unused
 }
 
 static void print_metric_only_json(struct perf_stat_config *config __maybe_unused,
-                                 void *ctx, const char *color __maybe_unused,
+                                 void *ctx,
+                                 enum metric_threshold_classify thresh __maybe_unused,
                                  const char *fmt,
                                  const char *unit, double val)
 {
@@ -636,7 +653,8 @@ static void new_line_metric(struct perf_stat_config *config __maybe_unused,
 }
 
 static void print_metric_header(struct perf_stat_config *config,
-                               void *ctx, const char *color __maybe_unused,
+                               void *ctx,
+                               enum metric_threshold_classify thresh __maybe_unused,
                                const char *fmt __maybe_unused,
                                const char *unit, double val __maybe_unused)
 {
@@ -810,7 +828,7 @@ static void printout(struct perf_stat_config *config, struct outstate *os,
 
        if (run == 0 || ena == 0 || counter->counts->scaled == -1) {
                if (config->metric_only) {
-                       pm(config, os, NULL, "", "", 0);
+                       pm(config, os, METRIC_THRESHOLD_UNKNOWN, "", "", 0);
                        return;
                }
 
@@ -865,7 +883,7 @@ static void printout(struct perf_stat_config *config, struct outstate *os,
                        perf_stat__print_shadow_stats(config, counter, uval, aggr_idx,
                                                      &out, &config->metric_events);
        } else {
-               pm(config, os, /*color=*/NULL, /*format=*/NULL, /*unit=*/"", /*val=*/0);
+               pm(config, os, METRIC_THRESHOLD_UNKNOWN, /*format=*/NULL, /*unit=*/"", /*val=*/0);
        }
 
        if (!config->metric_only) {
index 512890d50b6906df8bdc1a6305b0932bfc46ce27..ada787947e163e010161ef0d7250f091527b437d 100644 (file)
@@ -137,18 +137,14 @@ static enum stat_type evsel__stat_type(struct evsel *evsel)
        return STAT_NONE;
 }
 
-static const char *get_ratio_color(const double ratios[3], double val)
+static enum metric_threshold_classify get_ratio_thresh(const double ratios[3], double val)
 {
-       const char *color = PERF_COLOR_NORMAL;
+       assert(ratios[0] > ratios[1]);
+       assert(ratios[1] > ratios[2]);
 
-       if (val > ratios[0])
-               color = PERF_COLOR_RED;
-       else if (val > ratios[1])
-               color = PERF_COLOR_MAGENTA;
-       else if (val > ratios[2])
-               color = PERF_COLOR_YELLOW;
-
-       return color;
+       return val > ratios[1]
+               ? (val > ratios[0] ? METRIC_THRESHOLD_BAD : METRIC_THRESHOLD_NEARLY_BAD)
+               : (val > ratios[2] ? METRIC_THRESHOLD_LESS_GOOD : METRIC_THRESHOLD_GOOD);
 }
 
 static double find_stat(const struct evsel *evsel, int aggr_idx, enum stat_type type)
@@ -196,21 +192,21 @@ static void print_ratio(struct perf_stat_config *config,
                        const struct evsel *evsel, int aggr_idx,
                        double numerator, struct perf_stat_output_ctx *out,
                        enum stat_type denominator_type,
-                       const double color_ratios[3], const char *_unit)
+                       const double thresh_ratios[3], const char *_unit)
 {
        double denominator = find_stat(evsel, aggr_idx, denominator_type);
        double ratio = 0;
-       const char *color = NULL;
+       enum metric_threshold_classify thresh = METRIC_THRESHOLD_UNKNOWN;
        const char *fmt = NULL;
        const char *unit = NULL;
 
        if (numerator && denominator) {
                ratio = numerator / denominator * 100.0;
-               color = get_ratio_color(color_ratios, ratio);
+               thresh = get_ratio_thresh(thresh_ratios, ratio);
                fmt = "%7.2f%%";
                unit = _unit;
        }
-       out->print_metric(config, out->ctx, color, fmt, unit, ratio);
+       out->print_metric(config, out->ctx, thresh, fmt, unit, ratio);
 }
 
 static void print_stalled_cycles_front(struct perf_stat_config *config,
@@ -218,9 +214,9 @@ static void print_stalled_cycles_front(struct perf_stat_config *config,
                                int aggr_idx, double stalled,
                                struct perf_stat_output_ctx *out)
 {
-       static const double color_ratios[3] = {50.0, 30.0, 10.0};
+       const double thresh_ratios[3] = {50.0, 30.0, 10.0};
 
-       print_ratio(config, evsel, aggr_idx, stalled, out, STAT_CYCLES, color_ratios,
+       print_ratio(config, evsel, aggr_idx, stalled, out, STAT_CYCLES, thresh_ratios,
                    "frontend cycles idle");
 }
 
@@ -229,9 +225,9 @@ static void print_stalled_cycles_back(struct perf_stat_config *config,
                                int aggr_idx, double stalled,
                                struct perf_stat_output_ctx *out)
 {
-       static const double color_ratios[3] = {75.0, 50.0, 20.0};
+       const double thresh_ratios[3] = {75.0, 50.0, 20.0};
 
-       print_ratio(config, evsel, aggr_idx, stalled, out, STAT_CYCLES, color_ratios,
+       print_ratio(config, evsel, aggr_idx, stalled, out, STAT_CYCLES, thresh_ratios,
                    "backend cycles idle");
 }
 
@@ -240,9 +236,9 @@ static void print_branch_miss(struct perf_stat_config *config,
                        int aggr_idx, double misses,
                        struct perf_stat_output_ctx *out)
 {
-       static const double color_ratios[3] = {20.0, 10.0, 5.0};
+       const double thresh_ratios[3] = {20.0, 10.0, 5.0};
 
-       print_ratio(config, evsel, aggr_idx, misses, out, STAT_BRANCHES, color_ratios,
+       print_ratio(config, evsel, aggr_idx, misses, out, STAT_BRANCHES, thresh_ratios,
                    "of all branches");
 }
 
@@ -251,9 +247,9 @@ static void print_l1d_miss(struct perf_stat_config *config,
                        int aggr_idx, double misses,
                        struct perf_stat_output_ctx *out)
 {
-       static const double color_ratios[3] = {20.0, 10.0, 5.0};
+       const double thresh_ratios[3] = {20.0, 10.0, 5.0};
 
-       print_ratio(config, evsel, aggr_idx, misses, out, STAT_L1_DCACHE, color_ratios,
+       print_ratio(config, evsel, aggr_idx, misses, out, STAT_L1_DCACHE, thresh_ratios,
                    "of all L1-dcache accesses");
 }
 
@@ -262,9 +258,9 @@ static void print_l1i_miss(struct perf_stat_config *config,
                        int aggr_idx, double misses,
                        struct perf_stat_output_ctx *out)
 {
-       static const double color_ratios[3] = {20.0, 10.0, 5.0};
+       const double thresh_ratios[3] = {20.0, 10.0, 5.0};
 
-       print_ratio(config, evsel, aggr_idx, misses, out, STAT_L1_ICACHE, color_ratios,
+       print_ratio(config, evsel, aggr_idx, misses, out, STAT_L1_ICACHE, thresh_ratios,
                    "of all L1-icache accesses");
 }
 
@@ -273,9 +269,9 @@ static void print_ll_miss(struct perf_stat_config *config,
                        int aggr_idx, double misses,
                        struct perf_stat_output_ctx *out)
 {
-       static const double color_ratios[3] = {20.0, 10.0, 5.0};
+       const double thresh_ratios[3] = {20.0, 10.0, 5.0};
 
-       print_ratio(config, evsel, aggr_idx, misses, out, STAT_LL_CACHE, color_ratios,
+       print_ratio(config, evsel, aggr_idx, misses, out, STAT_LL_CACHE, thresh_ratios,
                    "of all LL-cache accesses");
 }
 
@@ -284,9 +280,9 @@ static void print_dtlb_miss(struct perf_stat_config *config,
                        int aggr_idx, double misses,
                        struct perf_stat_output_ctx *out)
 {
-       static const double color_ratios[3] = {20.0, 10.0, 5.0};
+       const double thresh_ratios[3] = {20.0, 10.0, 5.0};
 
-       print_ratio(config, evsel, aggr_idx, misses, out, STAT_DTLB_CACHE, color_ratios,
+       print_ratio(config, evsel, aggr_idx, misses, out, STAT_DTLB_CACHE, thresh_ratios,
                    "of all dTLB cache accesses");
 }
 
@@ -295,9 +291,9 @@ static void print_itlb_miss(struct perf_stat_config *config,
                        int aggr_idx, double misses,
                        struct perf_stat_output_ctx *out)
 {
-       static const double color_ratios[3] = {20.0, 10.0, 5.0};
+       const double thresh_ratios[3] = {20.0, 10.0, 5.0};
 
-       print_ratio(config, evsel, aggr_idx, misses, out, STAT_ITLB_CACHE, color_ratios,
+       print_ratio(config, evsel, aggr_idx, misses, out, STAT_ITLB_CACHE, thresh_ratios,
                    "of all iTLB cache accesses");
 }
 
@@ -306,9 +302,9 @@ static void print_cache_miss(struct perf_stat_config *config,
                        int aggr_idx, double misses,
                        struct perf_stat_output_ctx *out)
 {
-       static const double color_ratios[3] = {20.0, 10.0, 5.0};
+       const double thresh_ratios[3] = {20.0, 10.0, 5.0};
 
-       print_ratio(config, evsel, aggr_idx, misses, out, STAT_CACHE_REFS, color_ratios,
+       print_ratio(config, evsel, aggr_idx, misses, out, STAT_CACHE_REFS, thresh_ratios,
                    "of all cache refs");
 }
 
@@ -324,16 +320,16 @@ static void print_instructions(struct perf_stat_config *config,
                                find_stat(evsel, aggr_idx, STAT_STALLED_CYCLES_BACK));
 
        if (cycles) {
-               print_metric(config, ctxp, /*color=*/NULL, "%7.2f ", "insn per cycle",
-                            instructions / cycles);
+               print_metric(config, ctxp, METRIC_THRESHOLD_UNKNOWN, "%7.2f ",
+                            "insn per cycle", instructions / cycles);
        } else {
-               print_metric(config, ctxp, /*color=*/NULL, /*fmt=*/NULL, "insn per cycle", 0);
+               print_metric(config, ctxp, METRIC_THRESHOLD_UNKNOWN, /*fmt=*/NULL,
+                            "insn per cycle", 0);
        }
-
        if (max_stalled && instructions) {
                out->new_line(config, ctxp);
-               print_metric(config, ctxp, /*color=*/NULL, "%7.2f ", "stalled cycles per insn",
-                       max_stalled / instructions);
+               print_metric(config, ctxp, METRIC_THRESHOLD_UNKNOWN, "%7.2f ",
+                            "stalled cycles per insn", max_stalled / instructions);
        }
 }
 
@@ -347,9 +343,11 @@ static void print_cycles(struct perf_stat_config *config,
        if (cycles && nsecs) {
                double ratio = cycles / nsecs;
 
-               out->print_metric(config, out->ctx, /*color=*/NULL, "%8.3f", "GHz", ratio);
+               out->print_metric(config, out->ctx, METRIC_THRESHOLD_UNKNOWN, "%8.3f",
+                                 "GHz", ratio);
        } else {
-               out->print_metric(config, out->ctx, /*color=*/NULL, /*fmt=*/NULL, "GHz", 0);
+               out->print_metric(config, out->ctx, METRIC_THRESHOLD_UNKNOWN, /*fmt=*/NULL,
+                                 "GHz", 0);
        }
 }
 
@@ -363,10 +361,11 @@ static void print_nsecs(struct perf_stat_config *config,
        double wall_time = avg_stats(&walltime_nsecs_stats);
 
        if (wall_time) {
-               print_metric(config, ctxp, /*color=*/NULL, "%8.3f", "CPUs utilized",
+               print_metric(config, ctxp, METRIC_THRESHOLD_UNKNOWN, "%8.3f", "CPUs utilized",
                        nsecs / (wall_time * evsel->scale));
        } else {
-               print_metric(config, ctxp, /*color=*/NULL, /*fmt=*/NULL, "CPUs utilized", 0);
+               print_metric(config, ctxp, METRIC_THRESHOLD_UNKNOWN, /*fmt=*/NULL,
+                            "CPUs utilized", 0);
        }
 }
 
@@ -500,7 +499,7 @@ static void generic_metric(struct perf_stat_config *config,
        double ratio, scale, threshold;
        int i;
        void *ctxp = out->ctx;
-       const char *color = NULL;
+       enum metric_threshold_classify thresh = METRIC_THRESHOLD_UNKNOWN;
 
        pctx = expr__ctx_new();
        if (!pctx)
@@ -523,8 +522,8 @@ static void generic_metric(struct perf_stat_config *config,
                        if (metric_threshold &&
                            expr__parse(&threshold, pctx, metric_threshold) == 0 &&
                            !isnan(threshold)) {
-                               color = fpclassify(threshold) == FP_ZERO
-                                       ? PERF_COLOR_GREEN : PERF_COLOR_RED;
+                               thresh = fpclassify(threshold) == FP_ZERO
+                                       ? METRIC_THRESHOLD_GOOD : METRIC_THRESHOLD_BAD;
                        }
 
                        if (metric_unit && metric_name) {
@@ -539,22 +538,22 @@ static void generic_metric(struct perf_stat_config *config,
                                        scnprintf(metric_bf, sizeof(metric_bf),
                                          "%s  %s", unit, metric_name);
 
-                               print_metric(config, ctxp, color, "%8.1f",
+                               print_metric(config, ctxp, thresh, "%8.1f",
                                             metric_bf, ratio);
                        } else {
-                               print_metric(config, ctxp, color, "%8.2f",
+                               print_metric(config, ctxp, thresh, "%8.2f",
                                        metric_name ?
                                        metric_name :
                                        out->force_header ?  evsel->name : "",
                                        ratio);
                        }
                } else {
-                       print_metric(config, ctxp, color, /*fmt=*/NULL,
+                       print_metric(config, ctxp, thresh, /*fmt=*/NULL,
                                     out->force_header ?
                                     (metric_name ?: evsel->name) : "", 0);
                }
        } else {
-               print_metric(config, ctxp, color, /*fmt=*/NULL,
+               print_metric(config, ctxp, thresh, /*fmt=*/NULL,
                             out->force_header ?
                             (metric_name ?: evsel->name) : "", 0);
        }
@@ -725,7 +724,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
 
                                if (unit != ' ')
                                        snprintf(unit_buf, sizeof(unit_buf), "%c/sec", unit);
-                               print_metric(config, ctxp, /*color=*/NULL, "%8.3f",
+                               print_metric(config, ctxp, METRIC_THRESHOLD_UNKNOWN, "%8.3f",
                                             unit_buf, ratio);
                        } else {
                                num = 0;
@@ -736,8 +735,10 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
        perf_stat__print_shadow_stats_metricgroup(config, evsel, aggr_idx,
                                                  &num, NULL, out, metric_events);
 
-       if (num == 0)
-               print_metric(config, ctxp, /*color=*/NULL, /*fmt=*/NULL, /*unit=*/NULL, 0);
+       if (num == 0) {
+               print_metric(config, ctxp, METRIC_THRESHOLD_UNKNOWN,
+                            /*fmt=*/NULL, /*unit=*/NULL, 0);
+       }
 }
 
 /**
index a5f3d7d001017f0cb1a3d17734ca1e57b3f1add0..6f8cff3cd39a46b0dddd8ace0f04d85bfa4ef621 100644 (file)
@@ -154,8 +154,18 @@ struct evlist;
 extern struct stats walltime_nsecs_stats;
 extern struct rusage_stats ru_stats;
 
+enum metric_threshold_classify {
+       METRIC_THRESHOLD_UNKNOWN,
+       METRIC_THRESHOLD_BAD,
+       METRIC_THRESHOLD_NEARLY_BAD,
+       METRIC_THRESHOLD_LESS_GOOD,
+       METRIC_THRESHOLD_GOOD,
+};
+const char *metric_threshold_classify__color(enum metric_threshold_classify thresh);
+
 typedef void (*print_metric_t)(struct perf_stat_config *config,
-                              void *ctx, const char *color,
+                              void *ctx,
+                              enum metric_threshold_classify thresh,
                               const char *fmt,
                               const char *unit,
                               double val);