diff options
Diffstat (limited to 'utils/google-benchmark/include/benchmark/benchmark.h')
-rw-r--r-- | utils/google-benchmark/include/benchmark/benchmark.h | 172 |
1 files changed, 128 insertions, 44 deletions
diff --git a/utils/google-benchmark/include/benchmark/benchmark.h b/utils/google-benchmark/include/benchmark/benchmark.h index 193fffc4beaa..a0fd7c6e1cad 100644 --- a/utils/google-benchmark/include/benchmark/benchmark.h +++ b/utils/google-benchmark/include/benchmark/benchmark.h @@ -241,8 +241,21 @@ BENCHMARK(BM_test)->Unit(benchmark::kMillisecond); #define BENCHMARK_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) #endif +#ifndef __has_builtin +#define __has_builtin(x) 0 +#endif + +#if defined(__GNUC__) || __has_builtin(__builtin_unreachable) + #define BENCHMARK_UNREACHABLE() __builtin_unreachable() +#elif defined(_MSC_VER) + #define BENCHMARK_UNREACHABLE() __assume(false) +#else + #define BENCHMARK_UNREACHABLE() ((void)0) +#endif + namespace benchmark { class BenchmarkReporter; +class MemoryManager; void Initialize(int* argc, char** argv); @@ -255,7 +268,7 @@ bool ReportUnrecognizedArguments(int argc, char** argv); // of each matching benchmark. Otherwise run each matching benchmark and // report the results. // -// The second and third overload use the specified 'console_reporter' and +// The second and third overload use the specified 'display_reporter' and // 'file_reporter' respectively. 'file_reporter' will write to the file // specified // by '--benchmark_output'. If '--benchmark_output' is not given the @@ -263,16 +276,13 @@ bool ReportUnrecognizedArguments(int argc, char** argv); // // RETURNS: The number of matching benchmarks. size_t RunSpecifiedBenchmarks(); -size_t RunSpecifiedBenchmarks(BenchmarkReporter* console_reporter); -size_t RunSpecifiedBenchmarks(BenchmarkReporter* console_reporter, +size_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter); +size_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter, BenchmarkReporter* file_reporter); -// If this routine is called, peak memory allocation past this point in the -// benchmark is reported at the end of the benchmark report line. (It is -// computed by running the benchmark once with a single iteration and a memory -// tracer.) -// TODO(dominic) -// void MemoryUsage(); +// Register a MemoryManager instance that will be used to collect and report +// allocation measurements for benchmark runs. +void RegisterMemoryManager(MemoryManager* memory_manager); namespace internal { class Benchmark; @@ -363,11 +373,20 @@ class Counter { kAvgIterationsRate = kIsRate | kAvgIterations }; + enum OneK { + // 1'000 items per 1k + kIs1000 = 1000, + // 1'024 items per 1k + kIs1024 = 1024 + }; + double value; Flags flags; + OneK oneK; BENCHMARK_ALWAYS_INLINE - Counter(double v = 0., Flags f = kDefaults) : value(v), flags(f) {} + Counter(double v = 0., Flags f = kDefaults, OneK k = kIs1000) + : value(v), flags(f), oneK(k) {} BENCHMARK_ALWAYS_INLINE operator double const&() const { return value; } BENCHMARK_ALWAYS_INLINE operator double&() { return value; } @@ -406,22 +425,35 @@ struct Statistics { std::string name_; StatisticsFunc* compute_; - Statistics(std::string name, StatisticsFunc* compute) + Statistics(const std::string& name, StatisticsFunc* compute) : name_(name), compute_(compute) {} }; namespace internal { +struct BenchmarkInstance; class ThreadTimer; class ThreadManager; -enum ReportMode +enum AggregationReportMode #if defined(BENCHMARK_HAS_CXX11) : unsigned #else #endif -{ RM_Unspecified, // The mode has not been manually specified - RM_Default, // The mode is user-specified as default. - RM_ReportAggregatesOnly }; +{ + // The mode has not been manually specified + ARM_Unspecified = 0, + // The mode is user-specified. + // This may or may not be set when the following bit-flags are set. + ARM_Default = 1U << 0U, + // File reporter should only output aggregates. + ARM_FileReportAggregatesOnly = 1U << 1U, + // Display reporter should only output aggregates + ARM_DisplayReportAggregatesOnly = 1U << 2U, + // Both reporters should only display aggregates. + ARM_ReportAggregatesOnly = + ARM_FileReportAggregatesOnly | ARM_DisplayReportAggregatesOnly +}; + } // namespace internal // State is passed to a running Benchmark and contains state for the @@ -517,16 +549,21 @@ class State { // Set the number of bytes processed by the current benchmark // execution. This routine is typically called once at the end of a - // throughput oriented benchmark. If this routine is called with a - // value > 0, the report is printed in MB/sec instead of nanoseconds - // per iteration. + // throughput oriented benchmark. // // REQUIRES: a benchmark has exited its benchmarking loop. BENCHMARK_ALWAYS_INLINE - void SetBytesProcessed(int64_t bytes) { bytes_processed_ = bytes; } + void SetBytesProcessed(int64_t bytes) { + counters["bytes_per_second"] = + Counter(static_cast<double>(bytes), Counter::kIsRate, Counter::kIs1024); + } BENCHMARK_ALWAYS_INLINE - int64_t bytes_processed() const { return bytes_processed_; } + int64_t bytes_processed() const { + if (counters.find("bytes_per_second") != counters.end()) + return static_cast<int64_t>(counters.at("bytes_per_second")); + return 0; + } // If this routine is called with complexity_n > 0 and complexity report is // requested for the @@ -546,10 +583,17 @@ class State { // // REQUIRES: a benchmark has exited its benchmarking loop. BENCHMARK_ALWAYS_INLINE - void SetItemsProcessed(int64_t items) { items_processed_ = items; } + void SetItemsProcessed(int64_t items) { + counters["items_per_second"] = + Counter(static_cast<double>(items), benchmark::Counter::kIsRate); + } BENCHMARK_ALWAYS_INLINE - int64_t items_processed() const { return items_processed_; } + int64_t items_processed() const { + if (counters.find("items_per_second") != counters.end()) + return static_cast<int64_t>(counters.at("items_per_second")); + return 0; + } // If this routine is called, the specified label is printed at the // end of the benchmark report line for the currently executing @@ -612,9 +656,6 @@ class State { private: // items we don't need on the first cache line std::vector<int64_t> range_; - int64_t bytes_processed_; - int64_t items_processed_; - int64_t complexity_n_; public: @@ -625,12 +666,11 @@ class State { // Number of threads concurrently executing the benchmark. const int threads; - // TODO(EricWF) make me private + private: State(size_t max_iters, const std::vector<int64_t>& ranges, int thread_i, int n_threads, internal::ThreadTimer* timer, internal::ThreadManager* manager); - private: void StartKeepRunning(); // Implementation of KeepRunning() and KeepRunningBatch(). // is_batch must be true unless n is 1. @@ -638,7 +678,8 @@ class State { void FinishKeepRunning(); internal::ThreadTimer* timer_; internal::ThreadManager* manager_; - BENCHMARK_DISALLOW_COPY_AND_ASSIGN(State); + + friend struct internal::BenchmarkInstance; }; inline BENCHMARK_ALWAYS_INLINE bool State::KeepRunning() { @@ -827,8 +868,12 @@ class Benchmark { // Specify if each repetition of the benchmark should be reported separately // or if only the final statistics should be reported. If the benchmark // is not repeated then the single result is always reported. + // Applies to *ALL* reporters (display and file). Benchmark* ReportAggregatesOnly(bool value = true); + // Same as ReportAggregatesOnly(), but applies to display reporter only. + Benchmark* DisplayAggregatesOnly(bool value = true); + // If a particular benchmark is I/O bound, runs multiple threads internally or // if for some reason CPU timings are not representative, call this method. If // called, the elapsed time will be used to control how many iterations are @@ -888,9 +933,6 @@ class Benchmark { virtual void Run(State& state) = 0; - // Used inside the benchmark implementation - struct Instance; - protected: explicit Benchmark(const char* name); Benchmark(Benchmark const&); @@ -902,7 +944,7 @@ class Benchmark { friend class BenchmarkFamilies; std::string name_; - ReportMode report_mode_; + AggregationReportMode aggregation_report_mode_; std::vector<std::string> arg_names_; // Args for all benchmark runs std::vector<std::vector<int64_t> > args_; // Args for all benchmark runs TimeUnit time_unit_; @@ -1242,6 +1284,7 @@ struct CPUInfo { double cycles_per_second; std::vector<CacheInfo> caches; bool scaling_enabled; + std::vector<double> load_avg; static const CPUInfo& Get(); @@ -1250,6 +1293,15 @@ struct CPUInfo { BENCHMARK_DISALLOW_COPY_AND_ASSIGN(CPUInfo); }; +//Adding Struct for System Information +struct SystemInfo { + std::string name; + static const SystemInfo& Get(); + private: + SystemInfo(); + BENCHMARK_DISALLOW_COPY_AND_ASSIGN(SystemInfo); +}; + // Interface for custom benchmark result printers. // By default, benchmark reports are printed to stdout. However an application // can control the destination of the reports by calling @@ -1259,6 +1311,7 @@ class BenchmarkReporter { public: struct Context { CPUInfo const& cpu_info; + SystemInfo const& sys_info; // The number of chars in the longest benchmark name. size_t name_field_width; static const char* executable_name; @@ -1266,23 +1319,30 @@ class BenchmarkReporter { }; struct Run { + enum RunType { RT_Iteration, RT_Aggregate }; + Run() - : error_occurred(false), + : run_type(RT_Iteration), + error_occurred(false), iterations(1), time_unit(kNanosecond), real_accumulated_time(0), cpu_accumulated_time(0), - bytes_per_second(0), - items_per_second(0), max_heapbytes_used(0), complexity(oNone), complexity_lambda(), complexity_n(0), report_big_o(false), report_rms(false), - counters() {} - - std::string benchmark_name; + counters(), + has_memory_result(false), + allocs_per_iter(0.0), + max_bytes_used(0) {} + + std::string benchmark_name() const; + std::string run_name; + RunType run_type; // is this a measurement, or an aggregate? + std::string aggregate_name; std::string report_label; // Empty if not set by benchmark. bool error_occurred; std::string error_message; @@ -1304,10 +1364,6 @@ class BenchmarkReporter { // accumulated time. double GetAdjustedCPUTime() const; - // Zero if not set by benchmark. - double bytes_per_second; - double items_per_second; - // This is set to 0.0 if memory tracing is not enabled. double max_heapbytes_used; @@ -1324,6 +1380,11 @@ class BenchmarkReporter { bool report_rms; UserCounters counters; + + // Memory metrics. + bool has_memory_result; + double allocs_per_iter; + int64_t max_bytes_used; }; // Construct a BenchmarkReporter with the output stream set to 'std::cout' @@ -1438,6 +1499,29 @@ class BENCHMARK_DEPRECATED_MSG("The CSV Reporter will be removed in a future rel std::set<std::string> user_counter_names_; }; +// If a MemoryManager is registered, it can be used to collect and report +// allocation metrics for a run of the benchmark. +class MemoryManager { + public: + struct Result { + Result() : num_allocs(0), max_bytes_used(0) {} + + // The number of allocations made in total between Start and Stop. + int64_t num_allocs; + + // The peak memory use between Start and Stop. + int64_t max_bytes_used; + }; + + virtual ~MemoryManager() {} + + // Implement this to start recording allocation information. + virtual void Start() = 0; + + // Implement this to stop recording and fill out the given Result structure. + virtual void Stop(Result* result) = 0; +}; + inline const char* GetTimeUnitString(TimeUnit unit) { switch (unit) { case kMillisecond: @@ -1445,9 +1529,9 @@ inline const char* GetTimeUnitString(TimeUnit unit) { case kMicrosecond: return "us"; case kNanosecond: - default: return "ns"; } + BENCHMARK_UNREACHABLE(); } inline double GetTimeUnitMultiplier(TimeUnit unit) { @@ -1457,9 +1541,9 @@ inline double GetTimeUnitMultiplier(TimeUnit unit) { case kMicrosecond: return 1e6; case kNanosecond: - default: return 1e9; } + BENCHMARK_UNREACHABLE(); } } // namespace benchmark |