diff --git a/include/benchmark/benchmark.h b/include/benchmark/benchmark.h index e3857e717f..84e3a2710b 100644 --- a/include/benchmark/benchmark.h +++ b/include/benchmark/benchmark.h @@ -1895,7 +1895,10 @@ class BENCHMARK_EXPORT ConsoleReporter : public BenchmarkReporter { OO_Defaults = OO_ColorTabular }; explicit ConsoleReporter(OutputOptions opts_ = OO_Defaults) - : output_options_(opts_), name_field_width_(0), printed_header_(false) {} + : output_options_(opts_), + name_field_width_(0), + iterations_field_width_(0), + printed_header_(false) {} bool ReportContext(const Context& context) BENCHMARK_OVERRIDE; void ReportRuns(const std::vector& reports) BENCHMARK_OVERRIDE; @@ -1907,6 +1910,7 @@ class BENCHMARK_EXPORT ConsoleReporter : public BenchmarkReporter { OutputOptions output_options_; size_t name_field_width_; UserCounters prev_counters_; + size_t iterations_field_width_; bool printed_header_; }; diff --git a/src/benchmark_runner.cc b/src/benchmark_runner.cc index f7ae424397..dedfac03be 100644 --- a/src/benchmark_runner.cc +++ b/src/benchmark_runner.cc @@ -64,7 +64,7 @@ MemoryManager* memory_manager = nullptr; namespace { -static constexpr IterationCount kMaxIterations = 1000000000; +static constexpr IterationCount kMaxIterations = 1000000000000; const double kDefaultMinTime = std::strtod(::benchmark::kDefaultMinTimeStr, /*p_end*/ nullptr); diff --git a/src/console_reporter.cc b/src/console_reporter.cc index 10e05e133e..2f9ae6fca3 100644 --- a/src/console_reporter.cc +++ b/src/console_reporter.cc @@ -38,6 +38,7 @@ bool ConsoleReporter::ReportContext(const Context& context) { name_field_width_ = context.name_field_width; printed_header_ = false; prev_counters_.clear(); + iterations_field_width_ = std::string("Iterations").length(); PrintBasicContext(&GetErrorStream(), context); @@ -56,8 +57,9 @@ bool ConsoleReporter::ReportContext(const Context& context) { BENCHMARK_EXPORT void ConsoleReporter::PrintHeader(const Run& run) { std::string str = - FormatString("%-*s %13s %15s %12s", static_cast(name_field_width_), - "Benchmark", "Time", "CPU", "Iterations"); + FormatString("%-*s %13s %15s %*s", static_cast(name_field_width_), + "Benchmark", "Time", "CPU", + static_cast(iterations_field_width_) + 2, "Iterations"); if (!run.counters.empty()) { if (output_options_ & OO_Tabular) { for (auto const& c : run.counters) { @@ -73,6 +75,14 @@ void ConsoleReporter::PrintHeader(const Run& run) { BENCHMARK_EXPORT void ConsoleReporter::ReportRuns(const std::vector& reports) { + auto max_iterations = std::max_element(reports.begin(), reports.end(), + [](const Run& a, const Run& b) { + return a.iterations > b.iterations; + }) + ->iterations; + auto cur_iterations_field_width = std::max( + std::to_string(max_iterations).length(), iterations_field_width_); + for (const auto& run : reports) { // print the header: // --- if none was printed yet @@ -81,9 +91,12 @@ void ConsoleReporter::ReportRuns(const std::vector& reports) { // has different fields from the prev header print_header |= (output_options_ & OO_Tabular) && (!internal::SameNames(run.counters, prev_counters_)); + // --- or if the width of the iterations field has increased + print_header |= (cur_iterations_field_width > iterations_field_width_); if (print_header) { printed_header_ = true; prev_counters_ = run.counters; + iterations_field_width_ = cur_iterations_field_width; PrintHeader(run); } // As an alternative to printing the headers like this, we could sort @@ -171,7 +184,8 @@ void ConsoleReporter::PrintRunData(const Run& result) { } if (!result.report_big_o && !result.report_rms) { - printer(Out, COLOR_CYAN, "%10lld", result.iterations); + printer(Out, COLOR_CYAN, "%*lld", static_cast(iterations_field_width_), + result.iterations); } for (auto& c : result.counters) { diff --git a/test/user_counters_tabular_test.cc b/test/user_counters_tabular_test.cc index c98b769af2..cdb1e4894e 100644 --- a/test/user_counters_tabular_test.cc +++ b/test/user_counters_tabular_test.cc @@ -63,6 +63,9 @@ ADD_CASES(TC_CSVOut, {{"%csv_header," void BM_Counters_Tabular(benchmark::State& state) { for (auto _ : state) { + // This test requires a non-zero CPU time to avoid divide-by-zero + auto iterations = state.iterations(); + benchmark::DoNotOptimize(iterations); } namespace bm = benchmark; state.counters.insert({ @@ -430,6 +433,9 @@ CHECK_BENCHMARK_RESULTS("BM_CounterRates_Tabular/threads:%int", // set only some of the counters void BM_CounterSet0_Tabular(benchmark::State& state) { for (auto _ : state) { + // This test requires a non-zero CPU time to avoid divide-by-zero + auto iterations = state.iterations(); + benchmark::DoNotOptimize(iterations); } namespace bm = benchmark; state.counters.insert({ @@ -470,6 +476,9 @@ CHECK_BENCHMARK_RESULTS("BM_CounterSet0_Tabular", &CheckSet0); // again. void BM_CounterSet1_Tabular(benchmark::State& state) { for (auto _ : state) { + // This test requires a non-zero CPU time to avoid divide-by-zero + auto iterations = state.iterations(); + benchmark::DoNotOptimize(iterations); } namespace bm = benchmark; state.counters.insert({ @@ -514,6 +523,9 @@ CHECK_BENCHMARK_RESULTS("BM_CounterSet1_Tabular/threads:%int", &CheckSet1); // set only some of the counters, different set now. void BM_CounterSet2_Tabular(benchmark::State& state) { for (auto _ : state) { + // This test requires a non-zero CPU time to avoid divide-by-zero + auto iterations = state.iterations(); + benchmark::DoNotOptimize(iterations); } namespace bm = benchmark; state.counters.insert({