Skip to content

Commit 3ce9f21

Browse files
authored
Merge 707dd89 into 17298b2
2 parents 17298b2 + 707dd89 commit 3ce9f21

File tree

5 files changed

+127
-28
lines changed

5 files changed

+127
-28
lines changed

README.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,73 @@ When you're compiling in C++11 mode or later you can use `insert()` with
491491
state.counters["Baz"] = numBazs;
492492
```
493493
494+
### Counter reporting
495+
496+
When using the console reporter, by default, user counters are are printed at
497+
the end after the table, the same way as ``bytes_processed`` and
498+
``items_processed``. This is best for cases in which there are few counters,
499+
or where there are only a couple of lines per benchmark. Here's an example of
500+
the default output:
501+
502+
```
503+
------------------------------------------------------------------------------
504+
Benchmark Time CPU Iterations UserCounters...
505+
------------------------------------------------------------------------------
506+
BM_UserCounter/threads:8 2248 ns 10277 ns 68808 Bar=16 Bat=40 Baz=24 Foo=8
507+
BM_UserCounter/threads:1 9797 ns 9788 ns 71523 Bar=2 Bat=5 Baz=3 Foo=1024m
508+
BM_UserCounter/threads:2 4924 ns 9842 ns 71036 Bar=4 Bat=10 Baz=6 Foo=2
509+
BM_UserCounter/threads:4 2589 ns 10284 ns 68012 Bar=8 Bat=20 Baz=12 Foo=4
510+
BM_UserCounter/threads:8 2212 ns 10287 ns 68040 Bar=16 Bat=40 Baz=24 Foo=8
511+
BM_UserCounter/threads:16 1782 ns 10278 ns 68144 Bar=32 Bat=80 Baz=48 Foo=16
512+
BM_UserCounter/threads:32 1291 ns 10296 ns 68256 Bar=64 Bat=160 Baz=96 Foo=32
513+
BM_UserCounter/threads:4 2615 ns 10307 ns 68040 Bar=8 Bat=20 Baz=12 Foo=4
514+
BM_Factorial 26 ns 26 ns 26608979 40320
515+
BM_Factorial/real_time 26 ns 26 ns 26587936 40320
516+
BM_CalculatePiRange/1 16 ns 16 ns 45704255 0
517+
BM_CalculatePiRange/8 73 ns 73 ns 9520927 3.28374
518+
BM_CalculatePiRange/64 609 ns 609 ns 1140647 3.15746
519+
BM_CalculatePiRange/512 4900 ns 4901 ns 142696 3.14355
520+
```
521+
522+
If this doesn't suit you, you can print each counter as a table column by
523+
passing the flag `--benchmark_counters_tabular=true` to the benchmark
524+
application. This is best for cases in which there are a lot of counters, or
525+
a lot of lines per individual benchmark. Note that this will trigger a
526+
reprinting of the table header any time the counter set changes between
527+
individual benchmarks. Here's an example of corresponding output when
528+
`--benchmark_counters_tabular=true` is passed:
529+
530+
```
531+
---------------------------------------------------------------------------------------
532+
Benchmark Time CPU Iterations Bar Bat Baz Foo
533+
---------------------------------------------------------------------------------------
534+
BM_UserCounter/threads:8 2198 ns 9953 ns 70688 16 40 24 8
535+
BM_UserCounter/threads:1 9504 ns 9504 ns 73787 2 5 3 1
536+
BM_UserCounter/threads:2 4775 ns 9550 ns 72606 4 10 6 2
537+
BM_UserCounter/threads:4 2508 ns 9951 ns 70332 8 20 12 4
538+
BM_UserCounter/threads:8 2055 ns 9933 ns 70344 16 40 24 8
539+
BM_UserCounter/threads:16 1610 ns 9946 ns 70720 32 80 48 16
540+
BM_UserCounter/threads:32 1192 ns 9948 ns 70496 64 160 96 32
541+
BM_UserCounter/threads:4 2506 ns 9949 ns 70332 8 20 12 4
542+
--------------------------------------------------------------
543+
Benchmark Time CPU Iterations
544+
--------------------------------------------------------------
545+
BM_Factorial 26 ns 26 ns 26392245 40320
546+
BM_Factorial/real_time 26 ns 26 ns 26494107 40320
547+
BM_CalculatePiRange/1 15 ns 15 ns 45571597 0
548+
BM_CalculatePiRange/8 74 ns 74 ns 9450212 3.28374
549+
BM_CalculatePiRange/64 595 ns 595 ns 1173901 3.15746
550+
BM_CalculatePiRange/512 4752 ns 4752 ns 147380 3.14355
551+
BM_CalculatePiRange/4k 37970 ns 37972 ns 18453 3.14184
552+
BM_CalculatePiRange/32k 303733 ns 303744 ns 2305 3.14162
553+
BM_CalculatePiRange/256k 2434095 ns 2434186 ns 288 3.1416
554+
BM_CalculatePiRange/1024k 9721140 ns 9721413 ns 71 3.14159
555+
BM_CalculatePi/threads:8 2255 ns 9943 ns 70936
556+
```
557+
Note above the additional header printed when the benchmark changes from
558+
``BM_UserCounter`` to ``BM_Factorial``. This is because ``BM_Factorial`` does
559+
not have the same counter set as ``BM_UserCounter``.
560+
494561
## Exiting Benchmarks in Error
495562
496563
When errors caused by external influences, such as file I/O and network

include/benchmark/reporter.h

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -157,10 +157,17 @@ class BenchmarkReporter {
157157
// Simple reporter that outputs benchmark data to the console. This is the
158158
// default reporter used by RunSpecifiedBenchmarks().
159159
class ConsoleReporter : public BenchmarkReporter {
160-
public:
161-
enum OutputOptions { OO_None, OO_Color };
162-
explicit ConsoleReporter(OutputOptions color_output = OO_Color)
163-
: name_field_width_(0), color_output_(color_output == OO_Color) {}
160+
public:
161+
enum OutputOptions {
162+
OO_None = 0,
163+
OO_Color = 1,
164+
OO_Tabular = 2,
165+
OO_ColorTabular = OO_Color|OO_Tabular,
166+
OO_Defaults = OO_ColorTabular
167+
};
168+
explicit ConsoleReporter(OutputOptions opts_ = OO_Defaults)
169+
: output_options_(opts_), name_field_width_(0),
170+
prev_counters_(), printed_header_(false) {}
164171

165172
virtual bool ReportContext(const Context& context);
166173
virtual void ReportRuns(const std::vector<Run>& reports);
@@ -169,11 +176,10 @@ class ConsoleReporter : public BenchmarkReporter {
169176
virtual void PrintRunData(const Run& report);
170177
virtual void PrintHeader(const Run& report);
171178

179+
OutputOptions output_options_;
172180
size_t name_field_width_;
181+
UserCounters prev_counters_;
173182
bool printed_header_;
174-
175-
private:
176-
bool color_output_;
177183
};
178184

179185
class JSONReporter : public BenchmarkReporter {

src/benchmark.cc

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,11 @@ DEFINE_string(benchmark_color, "auto",
9191
"environment variable is set to a terminal type that supports "
9292
"colors.");
9393

94+
DEFINE_bool(benchmark_counters_tabular, false,
95+
"Whether to use tabular format when printing user counters to "
96+
"the console. Valid values: 'true'/'yes'/1, 'false'/'no'/0."
97+
"Defaults to false.");
98+
9499
DEFINE_int32(v, 0, "The level of verbose logging to output");
95100

96101
namespace benchmark {
@@ -510,10 +515,10 @@ void RunBenchmarks(const std::vector<Benchmark::Instance>& benchmarks,
510515
}
511516

512517
std::unique_ptr<BenchmarkReporter> CreateReporter(
513-
std::string const& name, ConsoleReporter::OutputOptions allow_color) {
518+
std::string const& name, ConsoleReporter::OutputOptions output_opts) {
514519
typedef std::unique_ptr<BenchmarkReporter> PtrType;
515520
if (name == "console") {
516-
return PtrType(new ConsoleReporter(allow_color));
521+
return PtrType(new ConsoleReporter(output_opts));
517522
} else if (name == "json") {
518523
return PtrType(new JSONReporter);
519524
} else if (name == "csv") {
@@ -546,16 +551,21 @@ size_t RunSpecifiedBenchmarks(BenchmarkReporter* console_reporter,
546551
std::unique_ptr<BenchmarkReporter> default_console_reporter;
547552
std::unique_ptr<BenchmarkReporter> default_file_reporter;
548553
if (!console_reporter) {
549-
auto output_opts = ConsoleReporter::OO_None;
550-
if (FLAGS_benchmark_color == "auto")
551-
output_opts = IsColorTerminal() ? ConsoleReporter::OO_Color
552-
: ConsoleReporter::OO_None;
553-
else
554-
output_opts = IsTruthyFlagValue(FLAGS_benchmark_color)
555-
? ConsoleReporter::OO_Color
556-
: ConsoleReporter::OO_None;
557-
default_console_reporter =
558-
internal::CreateReporter(FLAGS_benchmark_format, output_opts);
554+
int output_opts = ConsoleReporter::OO_Defaults;
555+
if ((FLAGS_benchmark_color == "auto" && IsColorTerminal()) ||
556+
IsTruthyFlagValue(FLAGS_benchmark_color)) {
557+
output_opts |= ConsoleReporter::OO_Color;
558+
} else {
559+
output_opts &= ~ConsoleReporter::OO_Color;
560+
}
561+
if(FLAGS_benchmark_counters_tabular) {
562+
output_opts |= ConsoleReporter::OO_Tabular;
563+
} else {
564+
output_opts &= ~ConsoleReporter::OO_Tabular;
565+
}
566+
default_console_reporter = internal::CreateReporter(
567+
FLAGS_benchmark_format,
568+
static_cast< ConsoleReporter::OutputOptions >(output_opts));
559569
console_reporter = default_console_reporter.get();
560570
}
561571
auto& Out = console_reporter->GetOutputStream();
@@ -614,6 +624,7 @@ void PrintUsageAndExit() {
614624
" [--benchmark_out=<filename>]\n"
615625
" [--benchmark_out_format=<json|console|csv>]\n"
616626
" [--benchmark_color={auto|true|false}]\n"
627+
" [--benchmark_counters_tabular={true|false}]\n"
617628
" [--v=<verbosity>]\n");
618629
exit(0);
619630
}
@@ -638,6 +649,8 @@ void ParseCommandLineFlags(int* argc, char** argv) {
638649
// "color_print" is the deprecated name for "benchmark_color".
639650
// TODO: Remove this.
640651
ParseStringFlag(argv[i], "color_print", &FLAGS_benchmark_color) ||
652+
ParseBoolFlag(argv[i], "benchmark_counters_tabular",
653+
&FLAGS_benchmark_counters_tabular) ||
641654
ParseInt32Flag(argv[i], "v", &FLAGS_v)) {
642655
for (int j = i; j != *argc - 1; ++j) argv[j] = argv[j + 1];
643656

src/console_reporter.cc

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,16 @@ namespace benchmark {
3636
bool ConsoleReporter::ReportContext(const Context& context) {
3737
name_field_width_ = context.name_field_width;
3838
printed_header_ = false;
39+
prev_counters_.clear();
3940

4041
PrintBasicContext(&GetErrorStream(), context);
4142

4243
#ifdef BENCHMARK_OS_WINDOWS
43-
if (color_output_ && &std::cout != &GetOutputStream()) {
44+
if ((output_options_ & OO_Color) && &std::cout != &GetOutputStream()) {
4445
GetErrorStream()
4546
<< "Color printing is only supported for stdout on windows."
4647
" Disabling color printing\n";
47-
color_output_ = false;
48+
output_options_ = static_cast< OutputOptions >(output_options_ & ~OO_Color);
4849
}
4950
#endif
5051

@@ -64,13 +65,21 @@ void ConsoleReporter::PrintHeader(const Run& run) {
6465

6566
void ConsoleReporter::ReportRuns(const std::vector<Run>& reports) {
6667
for (const auto& run : reports) {
67-
// print the header if none was printed yet
68-
if (!printed_header_) {
68+
// print the header:
69+
// --- if none was printed yet
70+
bool print_header = !printed_header_;
71+
// --- or if the format is tabular and this run
72+
// has different fields from the prev header
73+
print_header |= (output_options_ & OO_Tabular) &&
74+
(!internal::SameNames(run.counters, prev_counters_));
75+
if (print_header) {
6976
printed_header_ = true;
77+
prev_counters_ = run.counters;
7078
PrintHeader(run);
7179
}
7280
// As an alternative to printing the headers like this, we could sort
73-
// the benchmarks by header and then print like that.
81+
// the benchmarks by header and then print. But this would require
82+
// waiting for the full results before printing, or printing twice.
7483
PrintRunData(run);
7584
}
7685
}
@@ -86,8 +95,8 @@ static void IgnoreColorPrint(std::ostream& out, LogColor, const char* fmt,
8695
void ConsoleReporter::PrintRunData(const Run& result) {
8796
typedef void(PrinterFn)(std::ostream&, LogColor, const char*, ...);
8897
auto& Out = GetOutputStream();
89-
PrinterFn* printer =
90-
color_output_ ? (PrinterFn*)ColorPrintf : IgnoreColorPrint;
98+
PrinterFn* printer = (output_options_ & OO_Color) ?
99+
(PrinterFn*)ColorPrintf : IgnoreColorPrint;
91100
auto name_color =
92101
(result.report_big_o || result.report_rms) ? COLOR_BLUE : COLOR_GREEN;
93102
printer(Out, name_color, "%-*s ", name_field_width_,
@@ -134,7 +143,11 @@ void ConsoleReporter::PrintRunData(const Run& result) {
134143

135144
for (auto& c : result.counters) {
136145
auto const& s = HumanReadableNumber(c.second.value);
137-
printer(Out, COLOR_DEFAULT, " %s=%s", c.first.c_str(), s.c_str());
146+
if(output_options_ & OO_Tabular) {
147+
printer(Out, COLOR_DEFAULT, " %10s", s.c_str());
148+
} else {
149+
printer(Out, COLOR_DEFAULT, " %s=%s", c.first.c_str(), s.c_str());
150+
}
138151
}
139152

140153
if (!rate.empty()) {

src/counter.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ bool SameNames(UserCounters const& l, UserCounters const& r) {
5757
return false;
5858
}
5959
for (auto const& c : l) {
60-
if ( r.find(c.first) == r.end()) {
60+
if (r.find(c.first) == r.end()) {
6161
return false;
6262
}
6363
}

0 commit comments

Comments
 (0)