diff options
Diffstat (limited to 'tools/perf/util/stat-display.c')
-rw-r--r-- | tools/perf/util/stat-display.c | 108 |
1 files changed, 98 insertions, 10 deletions
diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c index a2bbdc25d979..7329b3340f88 100644 --- a/tools/perf/util/stat-display.c +++ b/tools/perf/util/stat-display.c @@ -25,6 +25,7 @@ #define CNTR_NOT_SUPPORTED "<not supported>" #define CNTR_NOT_COUNTED "<not counted>" +#define MGROUP_LEN 50 #define METRIC_LEN 38 #define EVNAME_LEN 32 #define COUNTS_LEN 18 @@ -364,16 +365,27 @@ static void new_line_std(struct perf_stat_config *config __maybe_unused, os->newline = true; } -static void do_new_line_std(struct perf_stat_config *config, - struct outstate *os) +static inline void __new_line_std_csv(struct perf_stat_config *config, + struct outstate *os) { fputc('\n', os->fh); if (os->prefix) fputs(os->prefix, os->fh); aggr_printout(config, os->evsel, os->id, os->aggr_nr); +} + +static inline void __new_line_std(struct outstate *os) +{ + fprintf(os->fh, " "); +} + +static void do_new_line_std(struct perf_stat_config *config, + struct outstate *os) +{ + __new_line_std_csv(config, os); if (config->aggr_mode == AGGR_NONE) fprintf(os->fh, " "); - fprintf(os->fh, " "); + __new_line_std(os); } static void print_metric_std(struct perf_stat_config *config, @@ -408,10 +420,7 @@ static void new_line_csv(struct perf_stat_config *config, void *ctx) struct outstate *os = ctx; int i; - fputc('\n', os->fh); - if (os->prefix) - fprintf(os->fh, "%s", os->prefix); - aggr_printout(config, os->evsel, os->id, os->aggr_nr); + __new_line_std_csv(config, os); for (i = 0; i < os->nfields; i++) fputs(config->csv_sep, os->fh); } @@ -462,6 +471,54 @@ static void new_line_json(struct perf_stat_config *config, void *ctx) aggr_printout(config, os->evsel, os->id, os->aggr_nr); } +static void print_metricgroup_header_json(struct perf_stat_config *config, + void *ctx, + const char *metricgroup_name) +{ + if (!metricgroup_name) + return; + + fprintf(config->output, "\"metricgroup\" : \"%s\"}", metricgroup_name); + new_line_json(config, ctx); +} + +static void print_metricgroup_header_csv(struct perf_stat_config *config, + void *ctx, + const char *metricgroup_name) +{ + struct outstate *os = ctx; + int i; + + if (!metricgroup_name) { + /* Leave space for running and enabling */ + for (i = 0; i < os->nfields - 2; i++) + fputs(config->csv_sep, os->fh); + return; + } + + for (i = 0; i < os->nfields; i++) + fputs(config->csv_sep, os->fh); + fprintf(config->output, "%s", metricgroup_name); + new_line_csv(config, ctx); +} + +static void print_metricgroup_header_std(struct perf_stat_config *config, + void *ctx, + const char *metricgroup_name) +{ + struct outstate *os = ctx; + int n; + + if (!metricgroup_name) { + __new_line_std(os); + return; + } + + n = fprintf(config->output, " %*s", EVNAME_LEN, metricgroup_name); + + fprintf(config->output, "%*s", MGROUP_LEN - n - 1, ""); +} + /* Filter out some columns that don't work well in metrics only mode */ static bool valid_only_metric(const char *unit) @@ -713,19 +770,23 @@ static void printout(struct perf_stat_config *config, struct outstate *os, struct perf_stat_output_ctx out; print_metric_t pm; new_line_t nl; + print_metricgroup_header_t pmh; bool ok = true; struct evsel *counter = os->evsel; if (config->csv_output) { pm = config->metric_only ? print_metric_only_csv : print_metric_csv; nl = config->metric_only ? new_line_metric : new_line_csv; + pmh = print_metricgroup_header_csv; os->nfields = 4 + (counter->cgrp ? 1 : 0); } else if (config->json_output) { pm = config->metric_only ? print_metric_only_json : print_metric_json; nl = config->metric_only ? new_line_metric : new_line_json; + pmh = print_metricgroup_header_json; } else { pm = config->metric_only ? print_metric_only : print_metric_std; nl = config->metric_only ? new_line_metric : new_line_std; + pmh = print_metricgroup_header_std; } if (run == 0 || ena == 0 || counter->counts->scaled == -1) { @@ -747,10 +808,11 @@ static void printout(struct perf_stat_config *config, struct outstate *os, out.print_metric = pm; out.new_line = nl; + out.print_metricgroup_header = pmh; out.ctx = os; out.force_header = false; - if (!config->metric_only) { + if (!config->metric_only && !counter->default_metricgroup) { abs_printout(config, os->id, os->aggr_nr, counter, uval, ok); print_noise(config, counter, noise, /*before_metric=*/true); @@ -758,8 +820,31 @@ static void printout(struct perf_stat_config *config, struct outstate *os, } if (ok) { - perf_stat__print_shadow_stats(config, counter, uval, aggr_idx, - &out, &config->metric_events); + if (!config->metric_only && counter->default_metricgroup) { + void *from = NULL; + + aggr_printout(config, os->evsel, os->id, os->aggr_nr); + /* Print out all the metricgroup with the same metric event. */ + do { + int num = 0; + + /* Print out the new line for the next new metricgroup. */ + if (from) { + if (config->json_output) + new_line_json(config, (void *)os); + else + __new_line_std_csv(config, os); + } + + print_noise(config, counter, noise, /*before_metric=*/true); + print_running(config, run, ena, /*before_metric=*/true); + from = perf_stat__print_shadow_stats_metricgroup(config, counter, aggr_idx, + &num, from, &out, + &config->metric_events); + } while (from != NULL); + } else + 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); } @@ -889,6 +974,9 @@ static void print_counter_aggrdata(struct perf_stat_config *config, ena = aggr->counts.ena; run = aggr->counts.run; + if (perf_stat__skip_metric_event(counter, &config->metric_events, ena, run)) + return; + if (val == 0 && should_skip_zero_counter(config, counter, &id)) return; |