42 static const int kValueWidth = 12;
43 static const int kValuePrecision = 6;
44 static const double kTolerance(1e-6);
48 Str(
const std::string& str_in,
int width_in) :
str(str_in),
width(width_in) {}
49 const std::string&
str;
52 std::ostream&
operator<<(std::ostream& out,
const Str& s) {
53 return out << std::setw(s.width) << s.str;
59 Double(
double value_in,
int width_in,
int precision_in)
67 std::ostream&
operator<<(std::ostream& out,
const Double& d) {
68 return out << std::right << std::setw(d.width)
69 << std::setprecision(d.precision) << d.value;
75 static const std::set<std::string> GetBenchmarkIdSet(
76 const std::vector<T>& items) {
77 std::set<std::string> ids;
78 const size_t count = items.size();
79 for (
size_t i = 0; i < count; ++i)
80 ids.insert(items[i].descriptor.id);
85 template <
typename T>
static void AddItem(
const T& item, Benchmark* b) {
86 DCHECK(
false) <<
"Unspecialized AddItem() called";
88 template <>
inline void AddItem(
const Benchmark::Constant& item, Benchmark* b) {
91 template <>
inline void AddItem(
const Benchmark::SampledVariable& item,
93 b->AddSampledVariable(item);
95 template <>
inline void AddItem(
const Benchmark::AccumulatedVariable& item,
97 b->AddAccumulatedVariable(item);
102 template <
typename T>
static size_t MergeBenchmarkItems(
103 const std::string& item_type,
const std::vector<T>& from_items,
104 std::set<std::string> ids, Benchmark* to) {
105 size_t num_conflicts = 0;
106 const size_t count = from_items.size();
107 for (
size_t i = 0; i < count; ++i) {
108 const std::string&
id = from_items[i].descriptor.id;
110 LOG(
ERROR) <<
"Conflicting " << item_type <<
" \"" <<
id
111 <<
"\" found while merging benchmarks";
114 AddItem(from_items[i], to);
117 return num_conflicts;
121 static void OutputConstantAsCsv(
122 const Benchmark::Constant& c, std::ostream& out) {
123 out << c.descriptor.id <<
","
124 << c.descriptor.description <<
","
125 << c.descriptor.group <<
","
127 << c.descriptor.units <<
","
133 static void OutputAccumulatedVariableAsCsv(
134 const Benchmark::AccumulatedVariable& v, std::ostream& out) {
135 out << v.descriptor.id <<
","
136 << v.descriptor.description <<
","
137 << v.descriptor.group <<
","
139 << v.descriptor.units <<
",";
142 if (v.minimum != v.maximum) {
143 out << v.minimum <<
"," << v.maximum <<
",";
149 if (v.standard_deviation != 0.0) {
150 out << v.standard_deviation <<
","
151 << (100.0 * v.standard_deviation / v.mean);
159 static void OutputKey(
const std::string&
type,
160 const Benchmark::Descriptor& descriptor,
163 out <<
" [" << type <<
"] " << std::right << Str(descriptor.id, id_width)
164 <<
": " << descriptor.description;
165 if (!descriptor.units.empty())
166 out <<
" (" << descriptor.units <<
")";
171 static void OutputConstantPretty(
172 const Benchmark::Constant& c,
176 out << Str(c.descriptor.id, id_width)
177 << Double(c.value, kValueWidth, kValuePrecision)
178 << Str(c.descriptor.units, units_width)
183 static void OutputAccumulatedVariablePretty(
184 const Benchmark::AccumulatedVariable& v,
188 const double rel_stddev =
189 v.mean == 0.0 ? 0.0 : 100.0 * v.standard_deviation / v.mean;
190 out << Str(v.descriptor.id, id_width)
191 << Double(v.mean, kValueWidth, kValuePrecision)
192 << Str(v.descriptor.units, units_width)
193 << Double(v.minimum, kValueWidth, kValuePrecision)
194 << Double(v.maximum, kValueWidth, kValuePrecision)
195 << Double(rel_stddev, kValueWidth - 2, 4) <<
" %"
214 const std::set<std::string> constant_ids =
216 const std::set<std::string> sampled_variable_ids =
218 const std::set<std::string> accumulated_variable_ids =
223 size_t num_conflicts =
224 MergeBenchmarkItems(
"Constant", from.
GetConstants(), constant_ids, to);
225 num_conflicts += MergeBenchmarkItems(
227 num_conflicts += MergeBenchmarkItems(
229 accumulated_variable_ids, to);
230 return num_conflicts;
236 out <<
"Entry ID, Description, Group, Average, Units, Minimum, Maximum, "
237 <<
"Standard Deviation, Relative Deviation %\n";
240 const std::vector<Benchmark::Constant>& constants = benchmark.
GetConstants();
241 const size_t num_constants = constants.size();
242 for (
size_t i = 0; i < num_constants; ++i)
243 OutputConstantAsCsv(constants[i], out);
246 const std::vector<Benchmark::SampledVariable>& sampled_variables =
248 const size_t num_sampled_variables = sampled_variables.size();
249 for (
size_t i = 0; i < num_sampled_variables; ++i)
250 OutputAccumulatedVariableAsCsv(
254 const std::vector<Benchmark::AccumulatedVariable>& accumulated_variables =
256 const size_t num_accumulated_variables = accumulated_variables.size();
257 for (
size_t i = 0; i < num_accumulated_variables; ++i)
258 OutputAccumulatedVariableAsCsv(accumulated_variables[i], out);
262 const std::string& indent,
264 out << indent <<
"{" << std::endl;
265 out << indent <<
" \"id\": \"" << c.
descriptor.
id <<
"\"," << std::endl
268 << indent <<
" \"group\": \"" << c.
descriptor.
group <<
"\"," << std::endl
269 << indent <<
" \"value\": " << c.
value <<
"," << std::endl
270 << indent <<
" \"units\": \"" << c.
descriptor.
units <<
"\"" << std::endl;
271 out << indent <<
"}";
275 const std::string& indent,
277 out << indent <<
"{" << std::endl;
278 out << indent <<
" \"id\": \"" << v.
descriptor.
id <<
"\"," << std::endl
281 << indent <<
" \"group\": \"" << v.
descriptor.
group <<
"\"," << std::endl
282 << indent <<
" \"mean\": " << v.
mean <<
"," << std::endl
287 out <<
"," << std::endl;
288 out << indent <<
" \"minimum\": " << v.
minimum <<
"," << std::endl
289 << indent <<
" \"maximum\": " << v.
maximum;
297 out <<
"," << std::endl;
299 << std::endl << indent
302 out << std::endl << indent <<
"}";
306 const std::string& indent_in,
308 const std::string indent = indent_in + std::string(
" ");
309 out << indent_in <<
"{" << std::endl;
312 const std::vector<Benchmark::Constant>& constants = benchmark.
GetConstants();
313 const size_t num_constants = constants.size();
315 out << indent_in <<
" \"constants\": [" << std::endl;
316 for (
size_t i = 0; i < num_constants; ++i) {
318 if (i < num_constants - 1)
319 out <<
"," << std::endl;
321 out << std::endl << indent_in <<
" ]";
325 const std::vector<Benchmark::SampledVariable>& sampled_variables =
327 const size_t num_sampled_variables = sampled_variables.size();
328 if (num_sampled_variables) {
330 out <<
"," << std::endl;
331 out << indent_in <<
" \"sampled_variables\": [" << std::endl;
332 for (
size_t i = 0; i < num_sampled_variables; ++i) {
336 if (i < num_sampled_variables - 1)
337 out <<
"," << std::endl;
339 out << std::endl << indent_in <<
" ]";
343 const std::vector<Benchmark::AccumulatedVariable>& accumulated_variables =
345 const size_t num_accumulated_variables = accumulated_variables.size();
346 if (num_accumulated_variables) {
347 if (num_constants || num_sampled_variables)
348 out <<
"," << std::endl;
349 out << indent_in <<
" \"accumulated_variables\": [" << std::endl;
350 for (
size_t i = 0; i < num_accumulated_variables; ++i) {
352 if (i < num_accumulated_variables - 1)
353 out <<
"," << std::endl;
355 out << std::endl << indent_in <<
" ]";
358 out << std::endl << indent_in <<
"}" << std::endl;
363 bool print_descriptions,
366 static const char kSeparator[] =
"----------------------------------------"
367 "---------------------------------------\n";
370 out << kSeparator <<
"Benchmark report for \"" << id_string <<
"\"\n\n";
372 const std::vector<Benchmark::Constant>& constants = benchmark.
GetConstants();
373 const std::vector<Benchmark::SampledVariable>& sampled_variables =
375 const std::vector<Benchmark::AccumulatedVariable>& accumulated_variables =
377 const size_t num_constants = constants.size();
378 const size_t num_sampled_variables = sampled_variables.size();
379 const size_t num_accumulated_variables = accumulated_variables.size();
382 static const int kMinIdWidth = 2;
383 size_t id_width_size_t = kMinIdWidth;
384 for (
size_t i = 0; i < num_constants; ++i)
385 id_width_size_t = std::max(id_width_size_t,
386 constants[i].descriptor.id.length());
387 for (
size_t i = 0; i < num_sampled_variables; ++i)
388 id_width_size_t = std::max(id_width_size_t,
389 sampled_variables[i].descriptor.id.length());
390 for (
size_t i = 0; i < num_accumulated_variables; ++i)
391 id_width_size_t = std::max(id_width_size_t,
392 accumulated_variables[i].descriptor.id.length());
393 const int id_width =
static_cast<int>(id_width_size_t);
396 static const int kMinUnitsWidth = 5;
397 size_t units_width_size_t = kMinUnitsWidth;
398 for (
size_t i = 0; i < num_constants; ++i)
399 units_width_size_t = std::max(units_width_size_t,
400 constants[i].descriptor.units.length());
401 for (
size_t i = 0; i < num_sampled_variables; ++i)
402 units_width_size_t = std::max(
403 units_width_size_t, sampled_variables[i].descriptor.units.length());
404 for (
size_t i = 0; i < num_accumulated_variables; ++i)
405 units_width_size_t = std::max(
406 units_width_size_t, accumulated_variables[i].descriptor.units.length());
407 ++units_width_size_t;
408 const int units_width =
static_cast<int>(units_width_size_t);
411 if (print_descriptions) {
412 for (
size_t i = 0; i < num_constants; ++i)
413 OutputKey(
"Constant", constants[i].descriptor, id_width, out);
414 for (
size_t i = 0; i < num_sampled_variables; ++i)
415 OutputKey(
"Variable", sampled_variables[i].descriptor, id_width, out);
416 for (
size_t i = 0; i < num_accumulated_variables; ++i)
417 OutputKey(
"Variable", accumulated_variables[i].descriptor, id_width, out);
423 out << Str(
"ID", id_width)
424 << Str(
"MEAN", kValueWidth)
425 << Str(
"UNITS", units_width)
426 << Str(
"MINIMUM", kValueWidth)
427 << Str(
"MAXIMUM", kValueWidth)
428 << Str(
"REL STDDEV", kValueWidth)
432 for (
size_t i = 0; i < num_constants; ++i)
433 OutputConstantPretty(constants[i], id_width, units_width, out);
436 for (
size_t i = 0; i < num_sampled_variables; ++i) {
438 sampled_variables[i]), id_width, units_width, out);
442 for (
size_t i = 0; i < num_accumulated_variables; ++i)
443 OutputAccumulatedVariablePretty(
444 accumulated_variables[i], id_width, units_width, out);
446 out << kSeparator << std::endl;
void OutputBenchmarkAsJson(const Benchmark &benchmark, const std::string &indent_in, std::ostream &out)
Outputs benchmark results as JSON, suitable for serialization and use in performance dashboards...
void OutputBenchmarkAsCsv(const Benchmark &benchmark, std::ostream &out)
Outputs benchmark results as CSV (comma-separated values), suitable for use in performance dashboards...
const std::vector< Constant > & GetConstants() const
Each of these returns the results for a given type of measurement.
#define LOG(severity)
Logs the streamed message unconditionally with a severity of severity.
const std::vector< SampledVariable > & GetSampledVariables() const
std::ostream & operator<<(std::ostream &os, const DateTime &dtime)
void OutputConstantAsJson(const Benchmark::Constant &c, const std::string &indent, std::ostream &out)
Outputs a Constant as JSON. See below for the output format.
static const AccumulatedVariable AccumulateSampledVariable(const SampledVariable &sampled_variable)
Converts a SampledVariable to an AccumulatedVariable by accumulating all of the samples.
size_t MergeBenchmarks(const Benchmark &from, Benchmark *to)
Public functions.
This struct represents a number that is constant over all samples.
const std::vector< AccumulatedVariable > & GetAccumulatedVariables() const
void OutputBenchmarkPretty(const std::string &id_string, bool print_descriptions, const Benchmark &benchmark, std::ostream &out)
Outputs benchmark results in pretty format.
Copyright 2016 Google Inc.
void OutputAccumulatedVariableAsJson(const Benchmark::AccumulatedVariable &v, const std::string &indent, std::ostream &out)
Outputs an AccumulatedVariable as JSON. See below for the output format.
The Benchmark class provides types and utilities to make it easier to create performance benchmarks...
double standard_deviation
const T Abs(const T &val)
Returns the absolute value of a number in a type-safe way.
This struct represents accumulated values for a variable.