Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf stat: Align CSV output for summary mode

The 'perf stat' subcommand supports the request for a summary of the
interval counter readings. But the summary lines break the CSV output
so it's hard for scripts to parse the result.

Before:

# perf stat -x, -I1000 --interval-count 1 --summary
1.001323097,8013.48,msec,cpu-clock,8013483384,100.00,8.013,CPUs utilized
1.001323097,270,,context-switches,8013513297,100.00,0.034,K/sec
1.001323097,13,,cpu-migrations,8013530032,100.00,0.002,K/sec
1.001323097,184,,page-faults,8013546992,100.00,0.023,K/sec
1.001323097,20574191,,cycles,8013551506,100.00,0.003,GHz
1.001323097,10562267,,instructions,8013564958,100.00,0.51,insn per cycle
1.001323097,2019244,,branches,8013575673,100.00,0.252,M/sec
1.001323097,106152,,branch-misses,8013585776,100.00,5.26,of all branches
8013.48,msec,cpu-clock,8013483384,100.00,7.984,CPUs utilized
270,,context-switches,8013513297,100.00,0.034,K/sec
13,,cpu-migrations,8013530032,100.00,0.002,K/sec
184,,page-faults,8013546992,100.00,0.023,K/sec
20574191,,cycles,8013551506,100.00,0.003,GHz
10562267,,instructions,8013564958,100.00,0.51,insn per cycle
2019244,,branches,8013575673,100.00,0.252,M/sec
106152,,branch-misses,8013585776,100.00,5.26,of all branches

The summary line loses the timestamp column, which breaks the CSV
output.

We add a column at the original 'timestamp' position and it just says
'summary' for the summary line.

After:

# perf stat -x, -I1000 --interval-count 1 --summary
1.001196053,8012.72,msec,cpu-clock,8012722903,100.00,8.013,CPUs utilized
1.001196053,218,,context-switches,8012753271,100.00,0.027,K/sec
1.001196053,9,,cpu-migrations,8012769767,100.00,0.001,K/sec
1.001196053,0,,page-faults,8012786257,100.00,0.000,K/sec
1.001196053,15004518,,cycles,8012790637,100.00,0.002,GHz
1.001196053,7954691,,instructions,8012804027,100.00,0.53,insn per cycle
1.001196053,1590259,,branches,8012814766,100.00,0.198,M/sec
1.001196053,82601,,branch-misses,8012824365,100.00,5.19,of all branches
summary,8012.72,msec,cpu-clock,8012722903,100.00,7.986,CPUs utilized
summary,218,,context-switches,8012753271,100.00,0.027,K/sec
summary,9,,cpu-migrations,8012769767,100.00,0.001,K/sec
summary,0,,page-faults,8012786257,100.00,0.000,K/sec
summary,15004518,,cycles,8012790637,100.00,0.002,GHz
summary,7954691,,instructions,8012804027,100.00,0.53,insn per cycle
summary,1590259,,branches,8012814766,100.00,0.198,M/sec
summary,82601,,branch-misses,8012824365,100.00,5.19,of all branches

Now it's easy for script to analyse the summary lines.

Of course, we also consider not to break possible existing scripts which
can continue to use the broken CSV format by using a new '--no-csv-summary.'
option.

# perf stat -x, -I1000 --interval-count 1 --summary --no-csv-summary
1.001213261,8012.67,msec,cpu-clock,8012672327,100.00,8.013,CPUs utilized
1.001213261,197,,context-switches,8012703742,100.00,24.586,/sec
1.001213261,9,,cpu-migrations,8012720902,100.00,1.123,/sec
1.001213261,644,,page-faults,8012738266,100.00,80.373,/sec
1.001213261,18350698,,cycles,8012744109,100.00,0.002,GHz
1.001213261,12745021,,instructions,8012759001,100.00,0.69,insn per cycle
1.001213261,2458033,,branches,8012770864,100.00,306.768,K/sec
1.001213261,102107,,branch-misses,8012781751,100.00,4.15,of all branches
8012.67,msec,cpu-clock,8012672327,100.00,7.985,CPUs utilized
197,,context-switches,8012703742,100.00,24.586,/sec
9,,cpu-migrations,8012720902,100.00,1.123,/sec
644,,page-faults,8012738266,100.00,80.373,/sec
18350698,,cycles,8012744109,100.00,0.002,GHz
12745021,,instructions,8012759001,100.00,0.69,insn per cycle
2458033,,branches,8012770864,100.00,306.768,K/sec
102107,,branch-misses,8012781751,100.00,4.15,of all branches

This option can be enabled in perf config by setting the variable
'stat.no-csv-summary'.

# perf config stat.no-csv-summary=true

# perf config -l
stat.no-csv-summary=true

# perf stat -x, -I1000 --interval-count 1 --summary
1.001330198,8013.28,msec,cpu-clock,8013279201,100.00,8.013,CPUs utilized
1.001330198,205,,context-switches,8013308394,100.00,25.583,/sec
1.001330198,10,,cpu-migrations,8013324681,100.00,1.248,/sec
1.001330198,0,,page-faults,8013340926,100.00,0.000,/sec
1.001330198,8027742,,cycles,8013344503,100.00,0.001,GHz
1.001330198,2871717,,instructions,8013356501,100.00,0.36,insn per cycle
1.001330198,553564,,branches,8013366204,100.00,69.081,K/sec
1.001330198,54021,,branch-misses,8013375952,100.00,9.76,of all branches
8013.28,msec,cpu-clock,8013279201,100.00,7.985,CPUs utilized
205,,context-switches,8013308394,100.00,25.583,/sec
10,,cpu-migrations,8013324681,100.00,1.248,/sec
0,,page-faults,8013340926,100.00,0.000,/sec
8027742,,cycles,8013344503,100.00,0.001,GHz
2871717,,instructions,8013356501,100.00,0.36,insn per cycle
553564,,branches,8013366204,100.00,69.081,K/sec
54021,,branch-misses,8013375952,100.00,9.76,of all branches

Signed-off-by: Jin Yao <yao.jin@linux.intel.com>
Acked-by: Andi Kleen <ak@linux.intel.com>
Acked-by: Jiri Olsa <jolsa@redhat.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Jin Yao <yao.jin@intel.com>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lore.kernel.org/lkml/20210319070156.20394-1-yao.jin@linux.intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Jin Yao and committed by
Arnaldo Carvalho de Melo
0bdad978 2c0cb9f5

+27
+9
tools/perf/Documentation/perf-stat.txt
··· 482 482 --summary:: 483 483 Print summary for interval mode (-I). 484 484 485 + --no-csv-summary:: 486 + Don't print 'summary' at the first column for CVS summary output. 487 + This option must be used with -x and --summary. 488 + 489 + This option can be enabled in perf config by setting the variable 490 + 'stat.no-csv-summary'. 491 + 492 + $ perf config stat.no-csv-summary=true 493 + 485 494 EXAMPLES 486 495 -------- 487 496
+7
tools/perf/builtin-stat.c
··· 1093 1093 stat_config.big_num = (set != 0); 1094 1094 } 1095 1095 1096 + void perf_stat__set_no_csv_summary(int set) 1097 + { 1098 + stat_config.no_csv_summary = (set != 0); 1099 + } 1100 + 1096 1101 static int stat__set_big_num(const struct option *opt __maybe_unused, 1097 1102 const char *s __maybe_unused, int unset) 1098 1103 { ··· 1254 1249 "threads of same physical core"), 1255 1250 OPT_BOOLEAN(0, "summary", &stat_config.summary, 1256 1251 "print summary for interval mode"), 1252 + OPT_BOOLEAN(0, "no-csv-summary", &stat_config.no_csv_summary, 1253 + "don't print 'summary' for CSV summary output"), 1257 1254 OPT_BOOLEAN(0, "quiet", &stat_config.quiet, 1258 1255 "don't print output (useful with record)"), 1259 1256 #ifdef HAVE_LIBPFM
+3
tools/perf/util/config.c
··· 457 457 if (!strcmp(var, "stat.big-num")) 458 458 perf_stat__set_big_num(perf_config_bool(var, value)); 459 459 460 + if (!strcmp(var, "stat.no-csv-summary")) 461 + perf_stat__set_no_csv_summary(perf_config_bool(var, value)); 462 + 460 463 /* Add other config variables here. */ 461 464 return 0; 462 465 }
+6
tools/perf/util/stat-display.c
··· 439 439 if (counter->cgrp) 440 440 os.nfields++; 441 441 } 442 + 443 + if (!config->no_csv_summary && config->csv_output && 444 + config->summary && !config->interval) { 445 + fprintf(config->output, "%16s%s", "summary", config->csv_sep); 446 + } 447 + 442 448 if (run == 0 || ena == 0 || counter->counts->scaled == -1) { 443 449 if (config->metric_only) { 444 450 pm(config, &os, NULL, "", "", 0);
+2
tools/perf/util/stat.h
··· 128 128 bool all_user; 129 129 bool percore_show_thread; 130 130 bool summary; 131 + bool no_csv_summary; 131 132 bool metric_no_group; 132 133 bool metric_no_merge; 133 134 bool stop_read_counter; ··· 161 160 }; 162 161 163 162 void perf_stat__set_big_num(int set); 163 + void perf_stat__set_no_csv_summary(int set); 164 164 165 165 void update_stats(struct stats *stats, u64 val); 166 166 double avg_stats(struct stats *stats);