diff options
Diffstat (limited to 'tools/perf/util/stat-display.c')
-rw-r--r-- | tools/perf/util/stat-display.c | 91 |
1 files changed, 49 insertions, 42 deletions
diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c index a5d72f4a515c..ba79f73e1cf5 100644 --- a/tools/perf/util/stat-display.c +++ b/tools/perf/util/stat-display.c @@ -115,14 +115,29 @@ static void print_running_csv(struct perf_stat_config *config, u64 run, u64 ena) config->csv_sep, run, config->csv_sep, enabled_percent); } struct outstate { - FILE *fh; + /* Std mode: insert a newline before the next metric */ bool newline; + /* JSON mode: track need for comma for a previous field or not */ bool first; - const char *prefix; - int nfields; - int aggr_nr; + /* Num CSV separators remaining to pad out when not all fields are printed */ + int csv_col_pad; + + /* + * The following don't track state across fields, but are here as a shortcut to + * pass data to the print functions. The alternative would be to update the + * function signatures of the entire print stack to pass them through. + */ + /* Place to output to */ + FILE * const fh; + /* Lines are timestamped in --interval-print mode */ + char timestamp[64]; + /* Num items aggregated in current line. See struct perf_stat_aggr.nr */ + int aggr_nr; + /* Core/socket/die etc ID for the current line */ struct aggr_cpu_id id; + /* Event for current line */ struct evsel *evsel; + /* Cgroup for current line */ struct cgroup *cgrp; }; @@ -419,8 +434,8 @@ 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); + if (config->interval) + fputs(os->timestamp, os->fh); aggr_printout(config, os, os->evsel, os->id, os->aggr_nr); } @@ -472,7 +487,7 @@ static void new_line_csv(struct perf_stat_config *config, void *ctx) int i; __new_line_std_csv(config, os); - for (i = 0; i < os->nfields; i++) + for (i = 0; i < os->csv_col_pad; i++) fputs(config->csv_sep, os->fh); } @@ -523,8 +538,8 @@ static void new_line_json(struct perf_stat_config *config, void *ctx) fputs("\n{", os->fh); os->first = true; - if (os->prefix) - json_out(os, "%s", os->prefix); + if (config->interval) + json_out(os, "%s", os->timestamp); aggr_printout(config, os, os->evsel, os->id, os->aggr_nr); } @@ -549,12 +564,12 @@ static void print_metricgroup_header_csv(struct perf_stat_config *config, if (!metricgroup_name) { /* Leave space for running and enabling */ - for (i = 0; i < os->nfields - 2; i++) + for (i = 0; i < os->csv_col_pad - 2; i++) fputs(config->csv_sep, os->fh); return; } - for (i = 0; i < os->nfields; i++) + for (i = 0; i < os->csv_col_pad; i++) fputs(config->csv_sep, os->fh); fprintf(config->output, "%s", metricgroup_name); new_line_csv(config, ctx); @@ -673,11 +688,6 @@ static void print_metric_only_json(struct perf_stat_config *config __maybe_unuse json_out(os, "\"%s\" : \"%s\"", unit, vals); } -static void new_line_metric(struct perf_stat_config *config __maybe_unused, - void *ctx __maybe_unused) -{ -} - static void print_metric_header(struct perf_stat_config *config, void *ctx, enum metric_threshold_classify thresh __maybe_unused, @@ -839,22 +849,23 @@ static void printout(struct perf_stat_config *config, struct outstate *os, 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; + nl = config->metric_only ? NULL : new_line_csv; pmh = print_metricgroup_header_csv; - os->nfields = 4 + (counter->cgrp ? 1 : 0); + os->csv_col_pad = 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; + nl = config->metric_only ? NULL : 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; + nl = config->metric_only ? NULL : new_line_std; pmh = print_metricgroup_header_std; } if (run == 0 || ena == 0 || counter->counts->scaled == -1) { if (config->metric_only) { - pm(config, os, METRIC_THRESHOLD_UNKNOWN, "", "", 0); + pm(config, os, METRIC_THRESHOLD_UNKNOWN, /*format=*/NULL, + /*unit=*/NULL, /*val=*/0); return; } @@ -909,7 +920,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, METRIC_THRESHOLD_UNKNOWN, /*format=*/NULL, /*unit=*/"", /*val=*/0); + pm(config, os, METRIC_THRESHOLD_UNKNOWN, /*format=*/NULL, /*unit=*/NULL, /*val=*/0); } if (!config->metric_only) { @@ -1095,13 +1106,13 @@ static void print_counter_aggrdata(struct perf_stat_config *config, os->first = true; fputc('{', output); } - if (os->prefix) { + if (config->interval) { if (config->json_output) - json_out(os, "%s", os->prefix); + json_out(os, "%s", os->timestamp); else - fprintf(output, "%s", os->prefix); + fprintf(output, "%s", os->timestamp); } else if (config->summary && config->csv_output && - !config->no_csv_summary && !config->interval) + !config->no_csv_summary) fprintf(output, "%s%s", "summary", config->csv_sep); } @@ -1128,11 +1139,11 @@ static void print_metric_begin(struct perf_stat_config *config, if (config->json_output) fputc('{', config->output); - if (os->prefix) { + if (config->interval) { if (config->json_output) - json_out(os, "%s", os->prefix); + json_out(os, "%s", os->timestamp); else - fprintf(config->output, "%s", os->prefix); + fprintf(config->output, "%s", os->timestamp); } evsel = evlist__first(evlist); id = config->aggr_map->map[aggr_idx]; @@ -1318,7 +1329,7 @@ static void print_metric_headers(struct perf_stat_config *config, struct perf_stat_output_ctx out = { .ctx = &os, .print_metric = print_metric_header, - .new_line = new_line_metric, + .new_line = NULL, .force_header = true, }; @@ -1353,20 +1364,20 @@ static void print_metric_headers(struct perf_stat_config *config, fputc('\n', config->output); } -static void prepare_interval(struct perf_stat_config *config, - char *prefix, size_t len, struct timespec *ts) +static void prepare_timestamp(struct perf_stat_config *config, + struct outstate *os, struct timespec *ts) { if (config->iostat_run) return; if (config->json_output) - scnprintf(prefix, len, "\"interval\" : %lu.%09lu", + scnprintf(os->timestamp, sizeof(os->timestamp), "\"interval\" : %lu.%09lu", (unsigned long) ts->tv_sec, ts->tv_nsec); else if (config->csv_output) - scnprintf(prefix, len, "%lu.%09lu%s", + scnprintf(os->timestamp, sizeof(os->timestamp), "%lu.%09lu%s", (unsigned long) ts->tv_sec, ts->tv_nsec, config->csv_sep); else - scnprintf(prefix, len, "%6lu.%09lu ", + scnprintf(os->timestamp, sizeof(os->timestamp), "%6lu.%09lu ", (unsigned long) ts->tv_sec, ts->tv_nsec); } @@ -1689,9 +1700,7 @@ void evlist__print_counters(struct evlist *evlist, struct perf_stat_config *conf int argc, const char **argv) { bool metric_only = config->metric_only; - int interval = config->interval; struct evsel *counter; - char buf[64]; struct outstate os = { .fh = config->output, .first = true, @@ -1702,10 +1711,8 @@ void evlist__print_counters(struct evlist *evlist, struct perf_stat_config *conf if (config->iostat_run) evlist->selected = evlist__first(evlist); - if (interval) { - os.prefix = buf; - prepare_interval(config, buf, sizeof(buf), ts); - } + if (config->interval) + prepare_timestamp(config, &os, ts); print_header(config, _target, evlist, argc, argv); @@ -1724,7 +1731,7 @@ void evlist__print_counters(struct evlist *evlist, struct perf_stat_config *conf case AGGR_THREAD: case AGGR_GLOBAL: if (config->iostat_run) { - iostat_print_counters(evlist, config, ts, buf, + iostat_print_counters(evlist, config, ts, os.timestamp, (iostat_print_counter_t)print_counter, &os); } else if (config->cgroup_list) { print_cgroup_counter(config, evlist, &os); |