summaryrefslogtreecommitdiff
path: root/tools/perf/util/stat-display.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/stat-display.c')
-rw-r--r--tools/perf/util/stat-display.c91
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);