[PATCH] perf stat: display cvs output for --null runs

From: Jiri Olsa
Date: Thu Apr 18 2019 - 03:45:07 EST


Adding support to display CVS values for --null runs as requested
by Ingo. It's only for --null run so it does not mess up with
standard CVS output.

For single --null run in CSV mode perf displays elapsed time:

$ perf stat --null -x ';' true
0.000496

For multiple --null run in CSV mode perf displays fields in this order:

- average elapsed time
- standard deviation

$ perf stat -r 5 --null -x ';' true
0.000339;0.000026

If --table is specified for above case, perf also displays new line
for every individual run with fields:

- elapsed time
- delta from average ellapsed time

$ perf stat -r 5 --table --null -x ';' true
0.000496;0.000106
0.000363;-0.000027
0.000355;-0.000035
0.000372;-0.000018
0.000361;-0.000029
0.000390;0.000027

The last line shows average elapsed time with standard deviation.

Requested-by: Ingo Molnar <mingo@xxxxxxxxxx>
Acked-by: Ingo Molnar <mingo@xxxxxxxxxx>
Link: http://lkml.kernel.org/n/tip-l44kt096zzsjwi3l9hjw1lle@xxxxxxxxxxxxxx
Signed-off-by: Jiri Olsa <jolsa@xxxxxxxxxx>
---
tools/perf/Documentation/perf-stat.txt | 30 ++++++++++++++++
tools/perf/util/stat-display.c | 48 +++++++++++++++++++-------
2 files changed, 65 insertions(+), 13 deletions(-)

diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 39c05f89104e..c07f018f3b4b 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -368,6 +368,36 @@ The fields are in this order:

Additional metrics may be printed with all earlier fields being empty.

+For single --null run in CSV mode perf displays elapsed time:
+
+ $ perf stat --null -x ';' true
+ 0.000496
+
+For multiple --null run in CSV mode perf displays fields in this order:
+
+ - average elapsed time
+ - standard deviation
+
+ $ perf stat -r 5 --null -x ';' true
+ 0.000339;0.000026
+
+If --table is specified for above case, perf also displays new line
+for every individual run with fields:
+
+ - elapsed time
+ - delta from average ellapsed time
+
+ $ perf stat -r 5 --table --null -x ';' true
+ 0.000496;0.000106
+ 0.000363;-0.000027
+ 0.000355;-0.000035
+ 0.000372;-0.000018
+ 0.000361;-0.000029
+ 0.000390;0.000027
+
+The last line shows average elapsed time with standard deviation.
+
+
SEE ALSO
--------
linkperf:perf-top[1], linkperf:perf-list[1]
diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c
index 3324f23c7efc..8cb4e37a0417 100644
--- a/tools/perf/util/stat-display.c
+++ b/tools/perf/util/stat-display.c
@@ -1013,22 +1013,29 @@ static void print_table(struct perf_stat_config *config,
while (tmp[indent] == ' ')
indent++;

- fprintf(output, "%*s# Table of individual measurements:\n", indent, "");
+ if (!config->csv_output)
+ fprintf(output, "%*s# Table of individual measurements:\n", indent, "");

for (idx = 0; idx < config->run_count; idx++) {
double run = (double) config->walltime_run[idx] / NSEC_PER_SEC;
int h, n = 1 + abs((int) (100.0 * (run - avg)/run) / 5);

- fprintf(output, " %17.*f (%+.*f) ",
- precision, run, precision, run - avg);
+ if (!config->csv_output) {
+ fprintf(output, " %17.*f (%+.*f) ",
+ precision, run, precision, run - avg);

- for (h = 0; h < n; h++)
- fprintf(output, "#");
+ for (h = 0; h < n; h++)
+ fprintf(output, "#");
+
+ } else {
+ fprintf(output, "%f%s%f", run, config->csv_sep, run - avg);
+ }

fprintf(output, "\n");
}

- fprintf(output, "\n%*s# Final result:\n", indent, "");
+ if (!config->csv_output)
+ fprintf(output, "\n%*s# Final result:\n", indent, "");
}

static double timeval2double(struct timeval *t)
@@ -1042,13 +1049,23 @@ static void print_footer(struct perf_stat_config *config)
FILE *output = config->output;
int n;

- if (!config->null_run)
+ /*
+ * Display csv output for null run, but do
+ * not mess up with standard csv mode.
+ */
+ if (config->csv_output && !config->null_run)
+ return;
+
+ if (!config->csv_output && !config->null_run)
fprintf(output, "\n");

if (config->run_count == 1) {
- fprintf(output, " %17.9f seconds time elapsed", avg);
+ if (!config->csv_output)
+ fprintf(output, " %17.9f seconds time elapsed", avg);
+ else
+ fprintf(output, "%f", avg);

- if (config->ru_display) {
+ if (!config->csv_output && config->ru_display) {
double ru_utime = timeval2double(&config->ru_data.ru_utime);
double ru_stime = timeval2double(&config->ru_data.ru_stime);

@@ -1067,11 +1084,16 @@ static void print_footer(struct perf_stat_config *config)
if (config->walltime_run_table)
print_table(config, output, precision, avg);

- fprintf(output, " %17.*f +- %.*f seconds time elapsed",
- precision, avg, precision, sd);
+ if (!config->csv_output) {
+ fprintf(output, " %17.*f +- %.*f seconds time elapsed",
+ precision, avg, precision, sd);

- print_noise_pct(config, sd, avg);
+ print_noise_pct(config, sd, avg);
+ } else {
+ fprintf(output, "%f%s%f", avg, config->csv_sep, sd);
+ }
}
+
fprintf(output, "\n\n");

if (config->print_free_counters_hint &&
@@ -1148,7 +1170,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist,
break;
}

- if (!interval && !config->csv_output)
+ if (!interval)
print_footer(config);

fflush(config->output);
--
2.20.1