reporter.h revision 30b48cb1b3a0c4fcc1887259bd215ad8738d21b4
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#ifndef BENCHMARK_REPORTER_H_ 15#define BENCHMARK_REPORTER_H_ 16 17#include <cassert> 18#include <iosfwd> 19#include <string> 20#include <utility> 21#include <vector> 22 23#include "benchmark_api.h" // For forward declaration of BenchmarkReporter 24 25namespace benchmark { 26 27// Interface for custom benchmark result printers. 28// By default, benchmark reports are printed to stdout. However an application 29// can control the destination of the reports by calling 30// RunSpecifiedBenchmarks and passing it a custom reporter object. 31// The reporter object must implement the following interface. 32class BenchmarkReporter { 33 public: 34 struct Context { 35 int num_cpus; 36 double mhz_per_cpu; 37 bool cpu_scaling_enabled; 38 39 // The number of chars in the longest benchmark name. 40 size_t name_field_width; 41 }; 42 43 struct Run { 44 Run() : 45 error_occurred(false), 46 iterations(1), 47 time_unit(kNanosecond), 48 real_accumulated_time(0), 49 cpu_accumulated_time(0), 50 bytes_per_second(0), 51 items_per_second(0), 52 max_heapbytes_used(0), 53 complexity(oNone), 54 complexity_n(0), 55 report_big_o(false), 56 report_rms(false) {} 57 58 std::string benchmark_name; 59 std::string report_label; // Empty if not set by benchmark. 60 bool error_occurred; 61 std::string error_message; 62 63 int64_t iterations; 64 TimeUnit time_unit; 65 double real_accumulated_time; 66 double cpu_accumulated_time; 67 68 // Return a value representing the real time per iteration in the unit 69 // specified by 'time_unit'. 70 // NOTE: If 'iterations' is zero the returned value represents the 71 // accumulated time. 72 double GetAdjustedRealTime() const; 73 74 // Return a value representing the cpu time per iteration in the unit 75 // specified by 'time_unit'. 76 // NOTE: If 'iterations' is zero the returned value represents the 77 // accumulated time. 78 double GetAdjustedCPUTime() const; 79 80 // Zero if not set by benchmark. 81 double bytes_per_second; 82 double items_per_second; 83 84 // This is set to 0.0 if memory tracing is not enabled. 85 double max_heapbytes_used; 86 87 // Keep track of arguments to compute asymptotic complexity 88 BigO complexity; 89 BigOFunc* complexity_lambda; 90 int complexity_n; 91 92 // Inform print function whether the current run is a complexity report 93 bool report_big_o; 94 bool report_rms; 95 }; 96 97 // Construct a BenchmarkReporter with the output stream set to 'std::cout' 98 // and the error stream set to 'std::cerr' 99 BenchmarkReporter(); 100 101 // Called once for every suite of benchmarks run. 102 // The parameter "context" contains information that the 103 // reporter may wish to use when generating its report, for example the 104 // platform under which the benchmarks are running. The benchmark run is 105 // never started if this function returns false, allowing the reporter 106 // to skip runs based on the context information. 107 virtual bool ReportContext(const Context& context) = 0; 108 109 // Called once for each group of benchmark runs, gives information about 110 // cpu-time and heap memory usage during the benchmark run. If the group 111 // of runs contained more than two entries then 'report' contains additional 112 // elements representing the mean and standard deviation of those runs. 113 // Additionally if this group of runs was the last in a family of benchmarks 114 // 'reports' contains additional entries representing the asymptotic 115 // complexity and RMS of that benchmark family. 116 virtual void ReportRuns(const std::vector<Run>& report) = 0; 117 118 // Called once and only once after ever group of benchmarks is run and 119 // reported. 120 virtual void Finalize() {} 121 122 // REQUIRES: The object referenced by 'out' is valid for the lifetime 123 // of the reporter. 124 void SetOutputStream(std::ostream* out) { 125 assert(out); 126 output_stream_ = out; 127 } 128 129 // REQUIRES: The object referenced by 'err' is valid for the lifetime 130 // of the reporter. 131 void SetErrorStream(std::ostream* err) { 132 assert(err); 133 error_stream_ = err; 134 } 135 136 std::ostream& GetOutputStream() const { 137 return *output_stream_; 138 } 139 140 std::ostream& GetErrorStream() const { 141 return *error_stream_; 142 } 143 144 virtual ~BenchmarkReporter(); 145 146 // Write a human readable string to 'out' representing the specified 147 // 'context'. 148 // REQUIRES: 'out' is non-null. 149 static void PrintBasicContext(std::ostream* out, Context const& context); 150 151 private: 152 std::ostream* output_stream_; 153 std::ostream* error_stream_; 154}; 155 156// Simple reporter that outputs benchmark data to the console. This is the 157// default reporter used by RunSpecifiedBenchmarks(). 158class ConsoleReporter : public BenchmarkReporter { 159public: 160 enum OutputOptions { 161 OO_None, 162 OO_Color 163 }; 164 explicit ConsoleReporter(OutputOptions color_output = OO_Color) 165 : color_output_(color_output == OO_Color) {} 166 167 virtual bool ReportContext(const Context& context); 168 virtual void ReportRuns(const std::vector<Run>& reports); 169 170protected: 171 virtual void PrintRunData(const Run& report); 172 size_t name_field_width_; 173 174private: 175 bool color_output_; 176}; 177 178class JSONReporter : public BenchmarkReporter { 179 public: 180 JSONReporter() : first_report_(true) {} 181 virtual bool ReportContext(const Context& context); 182 virtual void ReportRuns(const std::vector<Run>& reports); 183 virtual void Finalize(); 184 185 private: 186 void PrintRunData(const Run& report); 187 188 bool first_report_; 189}; 190 191class CSVReporter : public BenchmarkReporter { 192 public: 193 virtual bool ReportContext(const Context& context); 194 virtual void ReportRuns(const std::vector<Run>& reports); 195 196 private: 197 void PrintRunData(const Run& report); 198}; 199 200inline const char* GetTimeUnitString(TimeUnit unit) { 201 switch (unit) { 202 case kMillisecond: 203 return "ms"; 204 case kMicrosecond: 205 return "us"; 206 case kNanosecond: 207 default: 208 return "ns"; 209 } 210} 211 212inline double GetTimeUnitMultiplier(TimeUnit unit) { 213 switch (unit) { 214 case kMillisecond: 215 return 1e3; 216 case kMicrosecond: 217 return 1e6; 218 case kNanosecond: 219 default: 220 return 1e9; 221 } 222} 223 224} // end namespace benchmark 225#endif // BENCHMARK_REPORTER_H_ 226