aboutsummaryrefslogtreecommitdiff
path: root/include/benchmark/benchmark.h
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2018-11-04 03:05:48 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2018-11-04 03:05:48 +0000
commitd847f84a424ec4513a35dca61629f4b121e7e25c (patch)
tree293b6b89a54667c8fd3a2895acbb6448475daee6 /include/benchmark/benchmark.h
parentc68bc3578dbd02bee8c8cedd23dcbb1223b0fc81 (diff)
parent295f386099df283f36505edc41a8f656ac3bc11e (diff)
downloadgoogle-benchmark-d847f84a424ec4513a35dca61629f4b121e7e25c.tar.gz
Snap for 5110273 from 295f386099df283f36505edc41a8f656ac3bc11e to qt-release
Change-Id: I71d8d4f30d2e983b6c4ee7d8b8f3c34c10f3c446
Diffstat (limited to 'include/benchmark/benchmark.h')
-rw-r--r--include/benchmark/benchmark.h161
1 files changed, 117 insertions, 44 deletions
diff --git a/include/benchmark/benchmark.h b/include/benchmark/benchmark.h
index 193fffc..157a717 100644
--- a/include/benchmark/benchmark.h
+++ b/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_;
@@ -1266,23 +1308,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 +1353,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 +1369,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 +1488,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 +1518,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 +1530,9 @@ inline double GetTimeUnitMultiplier(TimeUnit unit) {
case kMicrosecond:
return 1e6;
case kNanosecond:
- default:
return 1e9;
}
+ BENCHMARK_UNREACHABLE();
}
} // namespace benchmark