CppBenchmark  1.0.4.0
C++ Benchmark Library
reporter_console.cpp
Go to the documentation of this file.
1 
10 
11 #include "benchmark/console.h"
12 #include "benchmark/environment.h"
13 #include "benchmark/version.h"
14 
15 #include <set>
16 #include <sstream>
17 
18 namespace CppBenchmark {
19 
21 {
22  _stream << Color::DARKGREY << GenerateSeparator('=') << std::endl;
23  _stream << Color::WHITE << "CppBenchmark report. Version " << version << std::endl;
24 }
25 
27 {
28  _stream << Color::DARKGREY << GenerateSeparator('=') << std::endl;
29  _stream << Color::WHITE << "CPU architecture: " << Color::LIGHTCYAN << System::CpuArchitecture() << std::endl;
30  _stream << Color::WHITE << "CPU logical cores: " << Color::LIGHTGREEN << System::CpuLogicalCores() << std::endl;
31  _stream << Color::WHITE << "CPU physical cores: " << Color::LIGHTGREEN << System::CpuPhysicalCores() << std::endl;
32  _stream << Color::WHITE << "CPU clock speed: " << Color::LIGHTGREEN << GenerateClockSpeed(System::CpuClockSpeed()) << std::endl;
33  _stream << Color::WHITE << "CPU Hyper-Threading: " << Color::LIGHTGREEN << (System::CpuHyperThreading() ? "enabled" : "disabled") << std::endl;
34  _stream << Color::WHITE << "RAM total: " << Color::YELLOW << GenerateDataSize(System::RamTotal()) << std::endl;
35  _stream << Color::WHITE << "RAM free: " << Color::YELLOW << GenerateDataSize(System::RamFree()) << std::endl;
36 }
37 
39 {
40  _stream << Color::DARKGREY << GenerateSeparator('=') << std::endl;
41  _stream << Color::WHITE << "OS version: " << Color::DARKGREY << Environment::OSVersion() << std::endl;
42  _stream << Color::WHITE << "OS bits: " << Color::DARKGREY << (Environment::Is64BitOS() ? "64-bit" : (Environment::Is32BitOS() ? "32-bit" : "<unknown>")) << std::endl;
43  _stream << Color::WHITE << "Process bits: " << Color::DARKGREY << (Environment::Is64BitProcess() ? "64-bit" : (Environment::Is32BitProcess() ? "32-bit" : "<unknown>")) << std::endl;
44  _stream << Color::WHITE << "Process configuration: " << Color::DARKGREY << (Environment::IsDebug() ? "debug" : (Environment::IsRelease() ? "release" : "<unknown>")) << std::endl;
45  time_t timestamp = Environment::Timestamp();
46  _stream << Color::WHITE << "Local timestamp: " << Color::DARKGREY << std::asctime(std::localtime(&timestamp));
47  _stream << Color::WHITE << "UTC timestamp: " << Color::DARKGREY << std::asctime(std::gmtime(&timestamp));
48 }
49 
50 void ReporterConsole::ReportBenchmark(const BenchmarkBase& benchmark, const Settings& settings)
51 {
52  _stream << Color::DARKGREY << GenerateSeparator('=') << std::endl;
53  _stream << Color::WHITE << "Benchmark: " << Color::LIGHTCYAN << benchmark.name() << std::endl;
54  _stream << Color::WHITE << "Attempts: " << Color::DARKGREY << settings.attempts() << std::endl;
55  if (settings.duration() > 0)
56  _stream << Color::WHITE << "Duration: " << Color::DARKGREY << settings.duration() << " seconds" << std::endl;
57  if (settings.operations() > 0)
58  _stream << Color::WHITE << "Operations: " << Color::DARKGREY << settings.operations() << std::endl;
59 }
60 
61 void ReporterConsole::ReportPhase(const PhaseCore& phase, const PhaseMetrics& metrics)
62 {
63  _stream << Color::DARKGREY << GenerateSeparator('-') << std::endl;
64  _stream << Color::WHITE << "Phase: " << Color::LIGHTCYAN << phase.name() << std::endl;
65  if (metrics.total_operations() > 1)
66  {
67  if (metrics.latency())
68  {
69  _stream << Color::WHITE << "Latency (Min): " << Color::YELLOW << GenerateTimePeriod(metrics.min_latency()) << "/op" << std::endl;
70  _stream << Color::WHITE << "Latency (Max): " << Color::YELLOW << GenerateTimePeriod(metrics.max_latency()) << "/op" << std::endl;
71  _stream << Color::WHITE << "Latency (Mean): " << Color::YELLOW << metrics.mean_latency() << std::endl;
72  _stream << Color::WHITE << "Latency (StDv): " << Color::YELLOW << metrics.stdv_latency() << std::endl;
73  }
74  else
75  {
76  _stream << Color::WHITE << "Average time: " << Color::YELLOW << GenerateTimePeriod(metrics.avg_time()) << "/op" << std::endl;
77  _stream << Color::WHITE << "Minimal time: " << Color::YELLOW << GenerateTimePeriod(metrics.min_time()) << "/op" << std::endl;
78  _stream << Color::WHITE << "Maximal time: " << Color::YELLOW << GenerateTimePeriod(metrics.max_time()) << "/op" << std::endl;
79  }
80  }
81  _stream << Color::WHITE << "Total time: " << Color::LIGHTRED << GenerateTimePeriod(metrics.total_time()) << std::endl;
82  if (metrics.total_operations() > 1)
83  _stream << Color::WHITE << "Total operations: " << Color::LIGHTGREEN << metrics.total_operations() << std::endl;
84  if (metrics.total_items() > 0)
85  _stream << Color::WHITE << "Total items: " << Color::LIGHTMAGENTA << metrics.total_items() << std::endl;
86  if (metrics.total_bytes() > 0)
87  _stream << Color::WHITE << "Total bytes: " << Color::MAGENTA << GenerateDataSize(metrics.total_bytes()) << std::endl;
88  if (metrics.total_operations() > 1)
89  _stream << Color::WHITE << "Operations throughput: " << Color::LIGHTGREEN << metrics.operations_per_second() << " ops/s" << std::endl;
90  if (metrics.total_items() > 0)
91  _stream << Color::WHITE << "Items throughput: " << Color::LIGHTMAGENTA << metrics.items_per_second() << " items/s" << std::endl;
92  if (metrics.total_bytes() > 0)
93  _stream << Color::WHITE << "Bytes throughput: " << Color::MAGENTA << GenerateDataSize(metrics.bytes_per_second()) << "/s" << std::endl;
94  if ((metrics.custom_int().size() > 0) || (metrics.custom_uint().size() > 0) ||
95  (metrics.custom_int64().size() > 0) || (metrics.custom_uint64().size() > 0) ||
96  (metrics.custom_flt().size() > 0) || (metrics.custom_dbl().size() > 0) ||
97  (metrics.custom_str().size() > 0))
98  {
99  _stream << Color::WHITE << "Custom values: " << std::endl;
100  std::set<std::string> names;
101  for (const auto& it : metrics.custom_int())
102  names.insert(it.first);
103  for (const auto& it : metrics.custom_uint())
104  names.insert(it.first);
105  for (const auto& it : metrics.custom_int64())
106  names.insert(it.first);
107  for (const auto& it : metrics.custom_uint64())
108  names.insert(it.first);
109  for (const auto& it : metrics.custom_flt())
110  names.insert(it.first);
111  for (const auto& it : metrics.custom_dbl())
112  names.insert(it.first);
113  for (const auto& it : metrics.custom_str())
114  names.insert(it.first);
115  for (const auto& name : names)
116  {
117  auto it_int = metrics.custom_int().find(name);
118  if (it_int != metrics.custom_int().end())
119  _stream << Color::DARKGREY << '\t' << it_int->first << ": " << Color::GREY << it_int->second << std::endl;
120  auto it_uint = metrics.custom_uint().find(name);
121  if (it_uint != metrics.custom_uint().end())
122  _stream << Color::DARKGREY << '\t' << it_uint->first << ": " << Color::GREY << it_uint->second << std::endl;
123  auto it_int64 = metrics.custom_int64().find(name);
124  if (it_int64 != metrics.custom_int64().end())
125  _stream << Color::DARKGREY << '\t' << it_int64->first << ": " << Color::GREY << it_int64->second << std::endl;
126  auto it_uint64 = metrics.custom_uint64().find(name);
127  if (it_uint64 != metrics.custom_uint64().end())
128  _stream << Color::DARKGREY << '\t' << it_uint64->first << ": " << Color::GREY << it_uint64->second << std::endl;
129  auto it_flt = metrics.custom_flt().find(name);
130  if (it_flt != metrics.custom_flt().end())
131  _stream << Color::DARKGREY << '\t' << it_flt->first << ": " << Color::GREY << it_flt->second << std::endl;
132  auto it_dbl = metrics.custom_dbl().find(name);
133  if (it_dbl != metrics.custom_dbl().end())
134  _stream << Color::DARKGREY << '\t' << it_dbl->first << ": " << Color::GREY << it_dbl->second << std::endl;
135  auto it_str = metrics.custom_str().find(name);
136  if (it_str != metrics.custom_str().end())
137  _stream << Color::DARKGREY << '\t' << it_str->first << ": " << Color::GREY << it_str->second << std::endl;
138  }
139  }
140 }
141 
143 {
144  _stream << Color::DARKGREY << GenerateSeparator('=') << std::endl;
145 }
146 
148 {
149  return std::string(79, ch);
150 }
151 
152 std::string ReporterConsole::GenerateClockSpeed(int64_t hertz)
153 {
154  std::ostringstream stream;
155 
156  int64_t abs_hertz = std::abs(hertz);
157 
158  if (abs_hertz >= 1000000000)
159  {
160  int64_t gigahertz = hertz / 1000000000;
161  int64_t megahertz = (hertz % 1000000000) / 1000000;
162  stream << gigahertz << '.' << ((megahertz < 100) ? "0" : "") << ((megahertz < 10) ? "0" : "") << megahertz << " GHz";
163  }
164  else if (abs_hertz >= 1000000)
165  {
166  int64_t megahertz = hertz / 1000000;
167  int64_t kilohertz = (hertz % 1000000) / 1000;
168  stream << megahertz << '.' << ((kilohertz < 100) ? "0" : "") << ((kilohertz < 10) ? "0" : "") << kilohertz << " MHz";
169  }
170  else if (abs_hertz >= 1000)
171  {
172  int64_t kilohertz = hertz / 1000;
173  hertz = hertz % 1000;
174  stream << kilohertz << '.' << ((hertz < 100) ? "0" : "") << ((hertz < 10) ? "0" : "") << hertz << " kHz";
175  }
176  else
177  stream << hertz << " Hz";
178 
179  return stream.str();
180 }
181 
182 std::string ReporterConsole::GenerateDataSize(int64_t bytes)
183 {
184  std::ostringstream stream;
185 
186  int64_t abs_bytes = std::abs(bytes);
187 
188  if (abs_bytes >= (1024ll * 1024ll * 1024ll * 1024ll))
189  {
190  int64_t tb = bytes / (1024ll * 1024ll * 1024ll * 1024ll);
191  int64_t gb = (bytes % (1024ll * 1024ll * 1024ll * 1024ll)) / (1024 * 1024 * 1024);
192  stream << tb << '.' << ((gb < 100) ? "0" : "") << ((gb < 10) ? "0" : "") << gb << " TiB";
193  }
194  else if (abs_bytes >= (1024 * 1024 * 1024))
195  {
196  int64_t gb = bytes / (1024 * 1024 * 1024);
197  int64_t mb = (bytes % (1024 * 1024 * 1024)) / (1024 * 1024);
198  stream << gb << '.' << ((mb < 100) ? "0" : "") << ((mb < 10) ? "0" : "") << mb << " GiB";
199  }
200  else if (abs_bytes >= (1024 * 1024))
201  {
202  int64_t mb = bytes / (1024 * 1024);
203  int64_t kb = (bytes % (1024 * 1024)) / 1024;
204  stream << mb << '.' << ((kb < 100) ? "0" : "") << ((kb < 10) ? "0" : "") << kb << " MiB";
205  }
206  else if (abs_bytes >= 1024)
207  {
208  int64_t kb = bytes / 1024;
209  bytes = bytes % 1024;
210  stream << kb << '.' << ((bytes < 100) ? "0" : "") << ((bytes < 10) ? "0" : "") << bytes << " KiB";
211  }
212  else
213  stream << bytes << " bytes";
214 
215  return stream.str();
216 }
217 
218 std::string ReporterConsole::GenerateTimePeriod(int64_t nanoseconds)
219 {
220  std::ostringstream stream;
221 
222  int64_t abs_nanoseconds = std::abs(nanoseconds);
223 
224  if (abs_nanoseconds >= (60 * 60 * 1000000000ll))
225  {
226  int64_t hours = nanoseconds / (60 * 60 * 1000000000ll);
227  int64_t minutes = ((nanoseconds % (60 * 60 * 1000000000ll)) / 1000000000) / 60;
228  int64_t seconds = ((nanoseconds % (60 * 60 * 1000000000ll)) / 1000000000) % 60;
229  int64_t milliseconds = ((nanoseconds % (60 * 60 * 1000000000ll)) % 1000000000) / 1000000;
230  stream << hours << ':' << ((minutes < 10) ? "0" : "") << minutes << ':' << ((seconds < 10) ? "0" : "") << seconds << '.' << ((milliseconds < 100) ? "0" : "") << ((milliseconds < 10) ? "0" : "") << milliseconds << " h";
231  }
232  else if (abs_nanoseconds >= (60 * 1000000000ll))
233  {
234  int64_t minutes = nanoseconds / (60 * 1000000000ll);
235  int64_t seconds = (nanoseconds % (60 * 1000000000ll)) / 1000000000;
236  int64_t milliseconds = ((nanoseconds % (60 * 1000000000ll)) % 1000000000) / 1000000;
237  stream << minutes << ':' << ((seconds < 10) ? "0" : "") << seconds << '.' << ((milliseconds < 100) ? "0" : "") << ((milliseconds < 10) ? "0" : "") << milliseconds << " m";
238  }
239  else if (abs_nanoseconds >= 1000000000)
240  {
241  int64_t seconds = nanoseconds / 1000000000;
242  int64_t milliseconds = (nanoseconds % 1000000000) / 1000000;
243  stream << seconds << '.' << ((milliseconds < 100) ? "0" : "") << ((milliseconds < 10) ? "0" : "") << milliseconds << " s";
244  }
245  else if (abs_nanoseconds >= 1000000)
246  {
247  int64_t milliseconds = nanoseconds / 1000000;
248  int64_t microseconds = (nanoseconds % 1000000) / 1000;
249  stream << milliseconds << '.' << ((microseconds < 100) ? "0" : "") << ((microseconds < 10) ? "0" : "") << microseconds << " ms";
250  }
251  else if (abs_nanoseconds >= 1000)
252  {
253  int64_t microseconds = nanoseconds / 1000;
254  nanoseconds = nanoseconds % 1000;
255  stream << microseconds << '.' << ((nanoseconds < 100) ? "0" : "") << ((nanoseconds < 10) ? "0" : "") << nanoseconds << " mcs";
256  }
257  else
258  stream << nanoseconds << " ns";
259 
260  return stream.str();
261 }
262 
263 } // namespace CppBenchmark
Benchmark base class.
const std::string & name() const
Get benchmark name.
static bool IsDebug()
Is compiled in debug mode?
Definition: environment.cpp:81
static std::string OSVersion()
Get OS version string.
static bool IsRelease()
Is compiled in release mode?
Definition: environment.cpp:86
static time_t Timestamp()
Get the current time in seconds.
static bool Is64BitProcess()
Is 64-bit running process?
Definition: environment.cpp:62
static bool Is64BitOS()
Is 64-bit OS?
Definition: environment.cpp:38
static bool Is32BitOS()
Is 32-bit OS?
Definition: environment.cpp:33
static bool Is32BitProcess()
Is 32-bit running process?
Definition: environment.cpp:57
Benchmark phase core.
Definition: phase_core.h:27
const std::string & name() const noexcept override
Get phase name.
Definition: phase_core.h:53
Benchmark phase metrics.
Definition: phase_metrics.h:37
int64_t total_bytes() const noexcept
Get total bytes processed in the phase.
Definition: phase_metrics.h:75
double mean_latency() const noexcept
Get latency mean value of the phase execution.
const std::map< std::string, unsigned > & custom_uint() const noexcept
Get custom unsigned integers map.
Definition: phase_metrics.h:87
int64_t total_time() const noexcept
Get total time of the phase execution.
Definition: phase_metrics.h:69
int64_t min_time() const noexcept
Get minimal time of the phase execution.
int64_t min_latency() const noexcept
Get latency minimal value of the phase execution.
double stdv_latency() const noexcept
Get latency standard deviation of the phase execution.
int64_t max_latency() const noexcept
Get latency maximal value of the phase execution.
const std::map< std::string, int64_t > & custom_int64() const noexcept
Get custom integers 64-bit map.
Definition: phase_metrics.h:89
const std::map< std::string, std::string > & custom_str() const noexcept
Get custom strings map.
Definition: phase_metrics.h:97
int64_t total_items() const noexcept
Get total items processed in the phase.
Definition: phase_metrics.h:73
int64_t avg_time() const noexcept
Get average time of the phase execution.
int64_t max_time() const noexcept
Get maximal time of the phase execution.
const std::map< std::string, uint64_t > & custom_uint64() const noexcept
Get custom unsigned integers 64-bit map.
Definition: phase_metrics.h:91
int64_t bytes_per_second() const noexcept
Get data throughput (bytes / second)
int64_t items_per_second() const noexcept
Get items throughput (items / second)
const std::map< std::string, int > & custom_int() const noexcept
Get custom integers map.
Definition: phase_metrics.h:85
int64_t operations_per_second() const noexcept
Get operations throughput (operations / second)
const std::map< std::string, float > & custom_flt() const noexcept
Get custom float map.
Definition: phase_metrics.h:93
bool latency() const noexcept
Is metrics contains latency values?
const std::map< std::string, double > & custom_dbl() const noexcept
Get custom doubles map.
Definition: phase_metrics.h:95
int64_t total_operations() const noexcept
Get total operations made in the phase.
Definition: phase_metrics.h:71
static std::string GenerateClockSpeed(int64_t hertz)
Generate clock speed string.
void ReportBenchmark(const BenchmarkBase &benchmark, const Settings &settings) override
Report current benchmark information.
static std::string GenerateSeparator(char ch)
Generate separator string.
void ReportEnvironment() override
Report environment information.
void ReportHeader() override
Report header.
void ReportPhase(const PhaseCore &phase, const PhaseMetrics &metrics) override
Report current phase information.
static std::string GenerateTimePeriod(int64_t nanoseconds)
Generate time period string.
void ReportSystem() override
Report system information.
void ReportFooter() override
Report footer.
static std::string GenerateDataSize(int64_t bytes)
Generate data size string.
Benchmark settings.
Definition: settings.h:32
int attempts() const noexcept
Get count of independent benchmark attempts.
Definition: settings.h:53
int64_t duration() const noexcept
Get benchmark duration in milliseconds.
Definition: settings.h:57
int64_t operations() const noexcept
Get count of operations.
Definition: settings.h:59
static int CpuPhysicalCores()
CPU physical cores count.
Definition: system.cpp:177
static std::string CpuArchitecture()
CPU architecture string.
Definition: system.cpp:128
static int64_t RamFree()
Free RAM in bytes.
Definition: system.cpp:331
static int64_t CpuClockSpeed()
CPU clock speed in Hz.
Definition: system.cpp:255
static bool CpuHyperThreading()
Is CPU Hyper-Threading enabled?
Definition: system.cpp:299
static int64_t RamTotal()
Total RAM in bytes.
Definition: system.cpp:305
static int CpuLogicalCores()
CPU logical cores count.
Definition: system.cpp:172
Console management definition.
Environment management definition.
C++ Benchmark project definitions.
Definition: barrier.h:15
const char version[]
Project version.
Definition: version.h:35
@ LIGHTMAGENTA
Light magenta color.
@ LIGHTCYAN
Light cyan color.
@ GREY
Grey color.
@ DARKGREY
Dark grey color.
@ LIGHTRED
Light red color.
@ YELLOW
Yellow color.
@ LIGHTGREEN
Light green color.
@ WHITE
White color.
@ MAGENTA
Magenta color.
Console reporter definition.
Version definition.