1 // Copyright 2015 Google Inc. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "benchmark/reporter.h"
16
17 #include <cstdint>
18 #include <cstdio>
19 #include <iostream>
20 #include <string>
21 #include <vector>
22
23 #include "check.h"
24 #include "colorprint.h"
25 #include "string_util.h"
26 #include "walltime.h"
27
28 namespace benchmark {
29
ReportContext(const Context & context)30 bool ConsoleReporter::ReportContext(const Context& context) {
31 name_field_width_ = context.name_field_width;
32
33 std::cerr << "Run on (" << context.num_cpus << " X " << context.mhz_per_cpu
34 << " MHz CPU " << ((context.num_cpus > 1) ? "s" : "") << ")\n";
35
36 std::cerr << LocalDateTimeString() << "\n";
37
38 if (context.cpu_scaling_enabled) {
39 std::cerr << "***WARNING*** CPU scaling is enabled, the benchmark "
40 "real time measurements may be noisy and will incur extra "
41 "overhead.\n";
42 }
43
44 #ifndef NDEBUG
45 std::cerr << "***WARNING*** Library was built as DEBUG. Timings may be "
46 "affected.\n";
47 #endif
48
49 int output_width = fprintf(stdout, "%-*s %10s %10s %10s\n",
50 static_cast<int>(name_field_width_), "Benchmark",
51 "Time(ns)", "CPU(ns)", "Iterations");
52 std::cout << std::string(output_width - 1, '-') << "\n";
53
54 return true;
55 }
56
ReportRuns(const std::vector<Run> & reports)57 void ConsoleReporter::ReportRuns(const std::vector<Run>& reports) {
58 if (reports.empty()) {
59 return;
60 }
61
62 for (Run const& run : reports) {
63 CHECK_EQ(reports[0].benchmark_name, run.benchmark_name);
64 PrintRunData(run);
65 }
66
67 if (reports.size() < 2) {
68 // We don't report aggregated data if there was a single run.
69 return;
70 }
71
72 Run mean_data;
73 Run stddev_data;
74 BenchmarkReporter::ComputeStats(reports, &mean_data, &stddev_data);
75
76 // Output using PrintRun.
77 PrintRunData(mean_data);
78 PrintRunData(stddev_data);
79 }
80
PrintRunData(const Run & result)81 void ConsoleReporter::PrintRunData(const Run& result) {
82 // Format bytes per second
83 std::string rate;
84 if (result.bytes_per_second > 0) {
85 rate = StrCat(" ", HumanReadableNumber(result.bytes_per_second), "B/s");
86 }
87
88 // Format items per second
89 std::string items;
90 if (result.items_per_second > 0) {
91 items = StrCat(" ", HumanReadableNumber(result.items_per_second),
92 " items/s");
93 }
94
95 double const multiplier = 1e9; // nano second multiplier
96 ColorPrintf(COLOR_GREEN, "%-*s ",
97 name_field_width_, result.benchmark_name.c_str());
98 if (result.iterations == 0) {
99 ColorPrintf(COLOR_YELLOW, "%10.0f %10.0f ",
100 result.real_accumulated_time * multiplier,
101 result.cpu_accumulated_time * multiplier);
102 } else {
103 ColorPrintf(COLOR_YELLOW, "%10.0f %10.0f ",
104 (result.real_accumulated_time * multiplier) /
105 (static_cast<double>(result.iterations)),
106 (result.cpu_accumulated_time * multiplier) /
107 (static_cast<double>(result.iterations)));
108 }
109 ColorPrintf(COLOR_CYAN, "%10lld", result.iterations);
110 ColorPrintf(COLOR_DEFAULT, "%*s %*s %s\n",
111 13, rate.c_str(),
112 18, items.c_str(),
113 result.report_label.c_str());
114 }
115
116 } // end namespace benchmark
117