CppBenchmark  1.0.4.0
C++ Benchmark Library
phase_metrics.cpp
Go to the documentation of this file.
1 
10 
11 #include "benchmark/system.h"
12 
13 #include <algorithm>
14 #include <cstdlib>
15 
16 #if defined(_MSC_VER)
17 #include <intrin.h>
18 #endif
19 
20 #include <hdr/hdr_histogram.h>
21 
22 namespace CppBenchmark {
23 
24 PhaseMetrics::PhaseMetrics() : _histogram(nullptr)
25 {
26  ResetMetrics();
27 }
28 
30 {
31  FreeLatencyHistogram();
32 }
33 
34 bool PhaseMetrics::latency() const noexcept
35 {
36  return (_histogram != nullptr);
37 }
38 
39 int64_t PhaseMetrics::min_latency() const noexcept
40 {
41  return latency() ? hdr_min((const hdr_histogram*)_histogram) : 0;
42 }
43 
44 int64_t PhaseMetrics::max_latency() const noexcept
45 {
46  return latency() ? hdr_max((const hdr_histogram*)_histogram) : 0;
47 }
48 
49 double PhaseMetrics::mean_latency() const noexcept
50 {
51  return latency() ? hdr_mean((const hdr_histogram*)_histogram) : 0;
52 }
53 
54 double PhaseMetrics::stdv_latency() const noexcept
55 {
56  return latency() ? hdr_stddev((const hdr_histogram*)_histogram) : 0;
57 }
58 
59 int64_t PhaseMetrics::avg_time() const noexcept
60 {
61  return (_total_operations > 0) ? (_total_time / _total_operations) : 0;
62 }
63 
64 int64_t PhaseMetrics::min_time() const noexcept
65 {
66  return _min_time;
67 }
68 
69 int64_t PhaseMetrics::max_time() const noexcept
70 {
71  return _max_time;
72 }
73 
74 int64_t PhaseMetrics::operations_per_second() const noexcept
75 {
76  if (_total_time <= 0)
77  return 0;
78 
79  return System::MulDiv64(_total_operations, 1000000000, _total_time);
80 }
81 
82 int64_t PhaseMetrics::items_per_second() const noexcept
83 {
84  if (_total_time <= 0)
85  return 0;
86 
87  return System::MulDiv64(_total_items, 1000000000, _total_time);
88 }
89 
90 int64_t PhaseMetrics::bytes_per_second() const noexcept
91 {
92  if (_total_time <= 0)
93  return 0;
94 
95  return System::MulDiv64(_total_bytes, 1000000000, _total_time);
96 }
97 
98 void PhaseMetrics::InitLatencyHistogram(const std::tuple<int64_t, int64_t, int>& latency) noexcept
99 {
100  int64_t lowest = std::get<0>(latency);
101  int64_t highest = std::get<1>(latency);
102  int significant = std::get<2>(latency);
103 
104  FreeLatencyHistogram();
105  int result = hdr_init(lowest, highest, significant, ((hdr_histogram**)&_histogram));
106  if (result != 0)
107  _histogram = nullptr;
108 }
109 
110 void PhaseMetrics::PrintLatencyHistogram(FILE* file, int32_t resolution) const noexcept
111 {
112  if ((_histogram != nullptr) && (file != nullptr))
113  {
114  hdr_percentiles_print((hdr_histogram*)_histogram, file, resolution, 1.0, CLASSIC);
115  }
116 }
117 
118 void PhaseMetrics::FreeLatencyHistogram() noexcept
119 {
120  if (_histogram != nullptr)
121  {
122  hdr_close((hdr_histogram*)_histogram);
123  _histogram = nullptr;
124  }
125 }
126 
127 void PhaseMetrics::AddLatency(int64_t latency) noexcept
128 {
129  if (_histogram != nullptr)
130  hdr_record_values((hdr_histogram*)_histogram, latency, 1);
131 }
132 
133 void PhaseMetrics::StartCollecting() noexcept
134 {
135  _iterstamp = _total_operations;
136  _timestamp = System::Timestamp();
137 }
138 
139 void PhaseMetrics::StopCollecting() noexcept
140 {
141  // Get iterations count & duration of the phase
142  int64_t iterations = _total_operations - _iterstamp;
143  int64_t duration = System::Timestamp() - _timestamp;
144 
145  // Get min & max time of the phase
146  int64_t min_time = (iterations > 0) ? (duration / iterations) : std::numeric_limits<int64_t>::max();
147  int64_t max_time = (iterations > 0) ? (duration / iterations) : std::numeric_limits<int64_t>::min();
148 
149  // Update time counters
150  if (min_time < _min_time)
151  _min_time = min_time;
152  if (max_time > _max_time)
153  _max_time = max_time;
154  _total_time += duration;
155 }
156 
157 void PhaseMetrics::MergeMetrics(PhaseMetrics& metrics)
158 {
159  // Choose best min time
160  if (metrics._min_time < _min_time)
161  _min_time = metrics._min_time;
162 
163  // Choose best max time
164  if (metrics._max_time > _max_time)
165  _max_time = metrics._max_time;
166 
167  // Merge custom hash tables
168  _custom_int.insert(metrics._custom_int.begin(), metrics._custom_int.end());
169  _custom_uint.insert(metrics._custom_uint.begin(), metrics._custom_uint.end());
170  _custom_int64.insert(metrics._custom_int64.begin(), metrics._custom_int64.end());
171  _custom_uint64.insert(metrics._custom_uint64.begin(), metrics._custom_uint64.end());
172  _custom_flt.insert(metrics._custom_flt.begin(), metrics._custom_flt.end());
173  _custom_dbl.insert(metrics._custom_dbl.begin(), metrics._custom_dbl.end());
174  _custom_str.insert(metrics._custom_str.begin(), metrics._custom_str.end());
175 
176  // Choose best total time with operations, items and bytes
177  if (metrics._total_time < _total_time)
178  {
179  std::swap(_histogram, metrics._histogram);
180  _total_time = metrics._total_time;
181  _total_operations = metrics._total_operations;
182  _total_items = metrics._total_items;
183  _total_bytes = metrics._total_bytes;
184 
185  // Overwrite metrics custom tables
186  for (const auto& it : metrics._custom_int)
187  _custom_int[it.first] = it.second;
188  for (const auto& it : metrics._custom_uint)
189  _custom_uint[it.first] = it.second;
190  for (const auto& it : metrics._custom_int64)
191  _custom_int64[it.first] = it.second;
192  for (const auto& it : metrics._custom_uint64)
193  _custom_uint64[it.first] = it.second;
194  for (const auto& it : metrics._custom_flt)
195  _custom_flt[it.first] = it.second;
196  for (const auto& it : metrics._custom_dbl)
197  _custom_dbl[it.first] = it.second;
198  for (const auto& it : metrics._custom_str)
199  _custom_str[it.first] = it.second;
200 
201  // Overwrite metrics threads value
202  _threads = metrics._threads;
203  }
204 }
205 
206 void PhaseMetrics::ResetMetrics() noexcept
207 {
208  FreeLatencyHistogram();
209  _min_time = std::numeric_limits<int64_t>::max();
210  _max_time = std::numeric_limits<int64_t>::min();
211  _total_time = 0;
212  _total_operations = 0;
213  _total_items = 0;
214  _total_bytes = 0;
215  _iterstamp = 0;
216  _timestamp = 0;
217  _threads = 1;
218 }
219 
220 } // namespace CppBenchmark
double mean_latency() const noexcept
Get latency mean value of the phase execution.
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.
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.
void AddLatency(int64_t latency) noexcept
Add latency value of the current phase.
int64_t bytes_per_second() const noexcept
Get data throughput (bytes / second)
int64_t items_per_second() const noexcept
Get items throughput (items / second)
int64_t operations_per_second() const noexcept
Get operations throughput (operations / second)
PhaseMetrics()
Default constructor.
bool latency() const noexcept
Is metrics contains latency values?
static uint64_t Timestamp()
Get the current timestamp in nanoseconds.
Definition: system.cpp:378
static uint64_t MulDiv64(uint64_t operant, uint64_t multiplier, uint64_t divider)
Calculate (operant * multiplier / divider) with 64-bit unsigned integer values.
Definition: system.cpp:429
C++ Benchmark project definitions.
Definition: barrier.h:15
Benchmark phase metrics definition.
System management definition.