Upgrade in-tree google benchmark to v1.1
git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@286029 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -153,6 +153,7 @@ BENCHMARK(BM_test)->Unit(benchmark::kMillisecond);
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "macros.h"
|
||||
@@ -173,7 +174,8 @@ void Initialize(int* argc, char** argv);
|
||||
// report the results.
|
||||
//
|
||||
// The second and third overload use the specified 'console_reporter' and
|
||||
// 'file_reporter' respectively. 'file_reporter' will write to the file specified
|
||||
// 'file_reporter' respectively. 'file_reporter' will write to the file
|
||||
// specified
|
||||
// by '--benchmark_output'. If '--benchmark_output' is not given the
|
||||
// 'file_reporter' is ignored.
|
||||
//
|
||||
@@ -183,7 +185,6 @@ size_t RunSpecifiedBenchmarks(BenchmarkReporter* console_reporter);
|
||||
size_t RunSpecifiedBenchmarks(BenchmarkReporter* console_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
|
||||
@@ -196,8 +197,9 @@ class Benchmark;
|
||||
class BenchmarkImp;
|
||||
class BenchmarkFamilies;
|
||||
|
||||
template <class T> struct Voider {
|
||||
typedef void type;
|
||||
template <class T>
|
||||
struct Voider {
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
template <class T, class = void>
|
||||
@@ -205,7 +207,7 @@ struct EnableIfString {};
|
||||
|
||||
template <class T>
|
||||
struct EnableIfString<T, typename Voider<typename T::basic_string>::type> {
|
||||
typedef int type;
|
||||
typedef int type;
|
||||
};
|
||||
|
||||
void UseCharPointer(char const volatile*);
|
||||
@@ -218,8 +220,7 @@ Benchmark* RegisterBenchmarkInternal(Benchmark*);
|
||||
int InitializeStreams();
|
||||
BENCHMARK_UNUSED static int stream_init_anchor = InitializeStreams();
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
// The DoNotOptimize(...) function can be used to prevent a value or
|
||||
// expression from being optimized away by the compiler. This function is
|
||||
@@ -228,73 +229,64 @@ BENCHMARK_UNUSED static int stream_init_anchor = InitializeStreams();
|
||||
#if defined(__GNUC__)
|
||||
template <class Tp>
|
||||
inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) {
|
||||
asm volatile("" : : "g"(value) : "memory");
|
||||
asm volatile("" : : "g"(value) : "memory");
|
||||
}
|
||||
// Force the compiler to flush pending writes to global memory. Acts as an
|
||||
// effective read/write barrier
|
||||
inline BENCHMARK_ALWAYS_INLINE void ClobberMemory() {
|
||||
asm volatile("" : : : "memory");
|
||||
asm volatile("" : : : "memory");
|
||||
}
|
||||
#else
|
||||
template <class Tp>
|
||||
inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) {
|
||||
internal::UseCharPointer(&reinterpret_cast<char const volatile&>(value));
|
||||
internal::UseCharPointer(&reinterpret_cast<char const volatile&>(value));
|
||||
}
|
||||
// FIXME Add ClobberMemory() for non-gnu compilers
|
||||
#endif
|
||||
|
||||
// TimeUnit is passed to a benchmark in order to specify the order of magnitude
|
||||
// for the measured time.
|
||||
enum TimeUnit {
|
||||
kNanosecond,
|
||||
kMicrosecond,
|
||||
kMillisecond
|
||||
};
|
||||
enum TimeUnit { kNanosecond, kMicrosecond, kMillisecond };
|
||||
|
||||
// BigO is passed to a benchmark in order to specify the asymptotic computational
|
||||
// complexity for the benchmark. In case oAuto is selected, complexity will be
|
||||
// BigO is passed to a benchmark in order to specify the asymptotic
|
||||
// computational
|
||||
// complexity for the benchmark. In case oAuto is selected, complexity will be
|
||||
// calculated automatically to the best fit.
|
||||
enum BigO {
|
||||
oNone,
|
||||
o1,
|
||||
oN,
|
||||
oNSquared,
|
||||
oNCubed,
|
||||
oLogN,
|
||||
oNLogN,
|
||||
oAuto,
|
||||
oLambda
|
||||
};
|
||||
enum BigO { oNone, o1, oN, oNSquared, oNCubed, oLogN, oNLogN, oAuto, oLambda };
|
||||
|
||||
// BigOFunc is passed to a benchmark in order to specify the asymptotic
|
||||
// BigOFunc is passed to a benchmark in order to specify the asymptotic
|
||||
// computational complexity for the benchmark.
|
||||
typedef double(BigOFunc)(int);
|
||||
|
||||
namespace internal {
|
||||
class ThreadTimer;
|
||||
class ThreadManager;
|
||||
|
||||
#if defined(BENCHMARK_HAS_CXX11)
|
||||
enum ReportMode : unsigned {
|
||||
#else
|
||||
enum ReportMode {
|
||||
#endif
|
||||
RM_Unspecified, // The mode has not been manually specified
|
||||
RM_Default, // The mode is user-specified as default.
|
||||
RM_ReportAggregatesOnly
|
||||
};
|
||||
}
|
||||
|
||||
// State is passed to a running Benchmark and contains state for the
|
||||
// benchmark to use.
|
||||
class State {
|
||||
public:
|
||||
State(size_t max_iters, const std::vector<int>& ranges,
|
||||
int thread_i, int n_threads);
|
||||
|
||||
public:
|
||||
// Returns true if the benchmark should continue through another iteration.
|
||||
// NOTE: A benchmark may not return from the test until KeepRunning() has
|
||||
// returned false.
|
||||
bool KeepRunning() {
|
||||
if (BENCHMARK_BUILTIN_EXPECT(!started_, false)) {
|
||||
assert(!finished_);
|
||||
started_ = true;
|
||||
ResumeTiming();
|
||||
StartKeepRunning();
|
||||
}
|
||||
bool const res = total_iterations_++ < max_iterations;
|
||||
if (BENCHMARK_BUILTIN_EXPECT(!res, false)) {
|
||||
assert(started_ && (!finished_ || error_occurred_));
|
||||
if (!error_occurred_) {
|
||||
PauseTiming();
|
||||
}
|
||||
// Total iterations now is one greater than max iterations. Fix this.
|
||||
total_iterations_ = max_iterations;
|
||||
finished_ = true;
|
||||
FinishKeepRunning();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -304,10 +296,11 @@ public:
|
||||
// Stop the benchmark timer. If not called, the timer will be
|
||||
// automatically stopped after KeepRunning() returns false for the first time.
|
||||
//
|
||||
// For threaded benchmarks the PauseTiming() function acts
|
||||
// like a barrier. I.e., the ith call by a particular thread to this
|
||||
// function will block until all active threads have made their ith call.
|
||||
// The timer will stop when the last thread has called this function.
|
||||
// For threaded benchmarks the PauseTiming() function only pauses the timing
|
||||
// for the current thread.
|
||||
//
|
||||
// NOTE: The "real time" measurement is per-thread. If different threads
|
||||
// report different measurements the largest one is reported.
|
||||
//
|
||||
// NOTE: PauseTiming()/ResumeTiming() are relatively
|
||||
// heavyweight, and so their use should generally be avoided
|
||||
@@ -319,11 +312,6 @@ public:
|
||||
// Start the benchmark timer. The timer is NOT running on entrance to the
|
||||
// benchmark function. It begins running after the first call to KeepRunning()
|
||||
//
|
||||
// For threaded benchmarks the ResumeTiming() function acts
|
||||
// like a barrier. I.e., the ith call by a particular thread to this
|
||||
// function will block until all active threads have made their ith call.
|
||||
// The timer will start when the last thread has called this function.
|
||||
//
|
||||
// NOTE: PauseTiming()/ResumeTiming() are relatively
|
||||
// heavyweight, and so their use should generally be avoided
|
||||
// within each benchmark iteration, if possible.
|
||||
@@ -335,10 +323,10 @@ public:
|
||||
// thread and report an error with the specified 'msg'. After this call
|
||||
// the user may explicitly 'return' from the benchmark.
|
||||
//
|
||||
// For threaded benchmarks only the current thread stops executing. If
|
||||
// multiple threads report an error only the first error message is used.
|
||||
// The current thread is no longer considered 'active' by
|
||||
// 'PauseTiming()' and 'ResumingTiming()'.
|
||||
// For threaded benchmarks only the current thread stops executing and future
|
||||
// calls to `KeepRunning()` will block until all threads have completed
|
||||
// the `KeepRunning()` loop. If multiple threads report an error only the
|
||||
// first error message is used.
|
||||
//
|
||||
// NOTE: Calling 'SkipWithError(...)' does not cause the benchmark to exit
|
||||
// the current scope immediately. If the function is called from within
|
||||
@@ -351,10 +339,8 @@ public:
|
||||
// is used instead of automatically measured time if UseManualTime() was
|
||||
// specified.
|
||||
//
|
||||
// For threaded benchmarks the SetIterationTime() function acts
|
||||
// like a barrier. I.e., the ith call by a particular thread to this
|
||||
// function will block until all threads have made their ith call.
|
||||
// The time will be set by the last thread to call this function.
|
||||
// For threaded benchmarks the final value will be set to the largest
|
||||
// reported values.
|
||||
void SetIterationTime(double seconds);
|
||||
|
||||
// Set the number of bytes processed by the current benchmark
|
||||
@@ -365,27 +351,21 @@ public:
|
||||
//
|
||||
// REQUIRES: a benchmark has exited its KeepRunning loop.
|
||||
BENCHMARK_ALWAYS_INLINE
|
||||
void SetBytesProcessed(size_t bytes) {
|
||||
bytes_processed_ = bytes;
|
||||
}
|
||||
void SetBytesProcessed(size_t bytes) { bytes_processed_ = bytes; }
|
||||
|
||||
BENCHMARK_ALWAYS_INLINE
|
||||
size_t bytes_processed() const {
|
||||
return bytes_processed_;
|
||||
}
|
||||
size_t bytes_processed() const { return bytes_processed_; }
|
||||
|
||||
// If this routine is called with complexity_n > 0 and complexity report is requested for the
|
||||
// family benchmark, then current benchmark will be part of the computation and complexity_n will
|
||||
// If this routine is called with complexity_n > 0 and complexity report is
|
||||
// requested for the
|
||||
// family benchmark, then current benchmark will be part of the computation
|
||||
// and complexity_n will
|
||||
// represent the length of N.
|
||||
BENCHMARK_ALWAYS_INLINE
|
||||
void SetComplexityN(int complexity_n) {
|
||||
complexity_n_ = complexity_n;
|
||||
}
|
||||
void SetComplexityN(int complexity_n) { complexity_n_ = complexity_n; }
|
||||
|
||||
BENCHMARK_ALWAYS_INLINE
|
||||
int complexity_length_n() {
|
||||
return complexity_n_;
|
||||
}
|
||||
int complexity_length_n() { return complexity_n_; }
|
||||
|
||||
// If this routine is called with items > 0, then an items/s
|
||||
// label is printed on the benchmark report line for the currently
|
||||
@@ -394,14 +374,10 @@ public:
|
||||
//
|
||||
// REQUIRES: a benchmark has exited its KeepRunning loop.
|
||||
BENCHMARK_ALWAYS_INLINE
|
||||
void SetItemsProcessed(size_t items) {
|
||||
items_processed_ = items;
|
||||
}
|
||||
void SetItemsProcessed(size_t items) { items_processed_ = items; }
|
||||
|
||||
BENCHMARK_ALWAYS_INLINE
|
||||
size_t items_processed() const {
|
||||
return items_processed_;
|
||||
}
|
||||
size_t items_processed() const { return items_processed_; }
|
||||
|
||||
// If this routine is called, the specified label is printed at the
|
||||
// end of the benchmark report line for the currently executing
|
||||
@@ -422,7 +398,7 @@ public:
|
||||
// has the nested typename `basic_string`. This typename should be provided
|
||||
// as an injected class name in the case of std::string.
|
||||
template <class StringType>
|
||||
void SetLabel(StringType const & str,
|
||||
void SetLabel(StringType const& str,
|
||||
typename internal::EnableIfString<StringType>::type = 1) {
|
||||
this->SetLabel(str.c_str());
|
||||
}
|
||||
@@ -430,8 +406,8 @@ public:
|
||||
// Range arguments for this run. CHECKs if the argument has been set.
|
||||
BENCHMARK_ALWAYS_INLINE
|
||||
int range(std::size_t pos = 0) const {
|
||||
assert(range_.size() > pos);
|
||||
return range_[pos];
|
||||
assert(range_.size() > pos);
|
||||
return range_[pos];
|
||||
}
|
||||
|
||||
BENCHMARK_DEPRECATED_MSG("use 'range(0)' instead")
|
||||
@@ -443,7 +419,7 @@ public:
|
||||
BENCHMARK_ALWAYS_INLINE
|
||||
size_t iterations() const { return total_iterations_; }
|
||||
|
||||
private:
|
||||
private:
|
||||
bool started_;
|
||||
bool finished_;
|
||||
size_t total_iterations_;
|
||||
@@ -455,17 +431,25 @@ private:
|
||||
|
||||
int complexity_n_;
|
||||
|
||||
public:
|
||||
// FIXME: Make this private somehow.
|
||||
bool error_occurred_;
|
||||
public:
|
||||
|
||||
public:
|
||||
// Index of the executing thread. Values from [0, threads).
|
||||
const int thread_index;
|
||||
// Number of threads concurrently executing the benchmark.
|
||||
const int threads;
|
||||
const size_t max_iterations;
|
||||
|
||||
private:
|
||||
// TODO make me private
|
||||
State(size_t max_iters, const std::vector<int>& ranges, int thread_i,
|
||||
int n_threads, internal::ThreadTimer* timer,
|
||||
internal::ThreadManager* manager);
|
||||
|
||||
private:
|
||||
void StartKeepRunning();
|
||||
void FinishKeepRunning();
|
||||
internal::ThreadTimer* timer_;
|
||||
internal::ThreadManager* manager_;
|
||||
BENCHMARK_DISALLOW_COPY_AND_ASSIGN(State);
|
||||
};
|
||||
|
||||
@@ -480,7 +464,7 @@ typedef void(Function)(State&);
|
||||
// Each method returns "this" so that multiple method calls can
|
||||
// chained into one expression.
|
||||
class Benchmark {
|
||||
public:
|
||||
public:
|
||||
virtual ~Benchmark();
|
||||
|
||||
// Note: the following methods all return "this" so that multiple
|
||||
@@ -499,7 +483,8 @@ public:
|
||||
// REQUIRES: The function passed to the constructor must accept an arg1.
|
||||
Benchmark* Range(int start, int limit);
|
||||
|
||||
// Run this benchmark once for all values in the range [start..limit] with specific step
|
||||
// Run this benchmark once for all values in the range [start..limit] with
|
||||
// specific step
|
||||
// REQUIRES: The function passed to the constructor must accept an arg1.
|
||||
Benchmark* DenseRange(int start, int limit, int step = 1);
|
||||
|
||||
@@ -512,10 +497,10 @@ public:
|
||||
// NOTE: This is a legacy C++03 interface provided for compatibility only.
|
||||
// New code should use 'Args'.
|
||||
Benchmark* ArgPair(int x, int y) {
|
||||
std::vector<int> args;
|
||||
args.push_back(x);
|
||||
args.push_back(y);
|
||||
return Args(args);
|
||||
std::vector<int> args;
|
||||
args.push_back(x);
|
||||
args.push_back(y);
|
||||
return Args(args);
|
||||
}
|
||||
|
||||
// Run this benchmark once for a number of values picked from the
|
||||
@@ -523,14 +508,21 @@ public:
|
||||
// REQUIRES: The function passed to the constructor must accept arg1, arg2 ...
|
||||
Benchmark* Ranges(const std::vector<std::pair<int, int> >& ranges);
|
||||
|
||||
// Equivalent to ArgNames({name})
|
||||
Benchmark* ArgName(const std::string& name);
|
||||
|
||||
// Set the argument names to display in the benchmark name. If not called,
|
||||
// only argument values will be shown.
|
||||
Benchmark* ArgNames(const std::vector<std::string>& names);
|
||||
|
||||
// Equivalent to Ranges({{lo1, hi1}, {lo2, hi2}}).
|
||||
// NOTE: This is a legacy C++03 interface provided for compatibility only.
|
||||
// New code should use 'Ranges'.
|
||||
Benchmark* RangePair(int lo1, int hi1, int lo2, int hi2) {
|
||||
std::vector<std::pair<int, int> > ranges;
|
||||
ranges.push_back(std::make_pair(lo1, hi1));
|
||||
ranges.push_back(std::make_pair(lo2, hi2));
|
||||
return Ranges(ranges);
|
||||
std::vector<std::pair<int, int> > ranges;
|
||||
ranges.push_back(std::make_pair(lo1, hi1));
|
||||
ranges.push_back(std::make_pair(lo2, hi2));
|
||||
return Ranges(ranges);
|
||||
}
|
||||
|
||||
// Pass this benchmark object to *func, which can customize
|
||||
@@ -538,8 +530,8 @@ public:
|
||||
// Threads, etc.
|
||||
Benchmark* Apply(void (*func)(Benchmark* benchmark));
|
||||
|
||||
// Set the range multiplier for non-dense range. If not called, the range multiplier
|
||||
// kRangeMultiplier will be used.
|
||||
// Set the range multiplier for non-dense range. If not called, the range
|
||||
// multiplier kRangeMultiplier will be used.
|
||||
Benchmark* RangeMultiplier(int multiplier);
|
||||
|
||||
// Set the minimum amount of time to use when running this benchmark. This
|
||||
@@ -564,15 +556,17 @@ public:
|
||||
// called, the cpu time used by the benchmark will be used.
|
||||
Benchmark* UseRealTime();
|
||||
|
||||
// If a benchmark must measure time manually (e.g. if GPU execution time is being
|
||||
// measured), call this method. If called, each benchmark iteration should call
|
||||
// If a benchmark must measure time manually (e.g. if GPU execution time is
|
||||
// being
|
||||
// measured), call this method. If called, each benchmark iteration should
|
||||
// call
|
||||
// SetIterationTime(seconds) to report the measured time, which will be used
|
||||
// to control how many iterations are run, and in the printing of items/second
|
||||
// or MB/second values.
|
||||
Benchmark* UseManualTime();
|
||||
|
||||
// Set the asymptotic computational complexity for the benchmark. If called
|
||||
// the asymptotic computational complexity will be shown on the output.
|
||||
// the asymptotic computational complexity will be shown on the output.
|
||||
Benchmark* Complexity(BigO complexity = benchmark::oAuto);
|
||||
|
||||
// Set the asymptotic computational complexity for the benchmark. If called
|
||||
@@ -600,6 +594,12 @@ public:
|
||||
// Foo in 16 threads
|
||||
Benchmark* ThreadRange(int min_threads, int max_threads);
|
||||
|
||||
// For each value n in the range, run this benchmark once using n threads.
|
||||
// min_threads and max_threads are always included in the range.
|
||||
// stride specifies the increment. E.g. DenseThreadRange(1, 8, 3) starts
|
||||
// a benchmark with 1, 4, 7 and 8 threads.
|
||||
Benchmark* DenseThreadRange(int min_threads, int max_threads, int stride = 1);
|
||||
|
||||
// Equivalent to ThreadRange(NumCPUs(), NumCPUs())
|
||||
Benchmark* ThreadPerCpu();
|
||||
|
||||
@@ -608,25 +608,43 @@ public:
|
||||
// Used inside the benchmark implementation
|
||||
struct Instance;
|
||||
|
||||
protected:
|
||||
protected:
|
||||
explicit Benchmark(const char* name);
|
||||
Benchmark(Benchmark const&);
|
||||
void SetName(const char* name);
|
||||
|
||||
private:
|
||||
int ArgsCnt() const;
|
||||
|
||||
static void AddRange(std::vector<int>* dst, int lo, int hi, int mult);
|
||||
|
||||
private:
|
||||
friend class BenchmarkFamilies;
|
||||
BenchmarkImp* imp_;
|
||||
|
||||
std::string name_;
|
||||
ReportMode report_mode_;
|
||||
std::vector<std::string> arg_names_; // Args for all benchmark runs
|
||||
std::vector<std::vector<int> > args_; // Args for all benchmark runs
|
||||
TimeUnit time_unit_;
|
||||
int range_multiplier_;
|
||||
double min_time_;
|
||||
int repetitions_;
|
||||
bool use_real_time_;
|
||||
bool use_manual_time_;
|
||||
BigO complexity_;
|
||||
BigOFunc* complexity_lambda_;
|
||||
std::vector<int> thread_counts_;
|
||||
|
||||
Benchmark& operator=(Benchmark const&);
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace internal
|
||||
|
||||
// Create and register a benchmark with the specified 'name' that invokes
|
||||
// the specified functor 'fn'.
|
||||
//
|
||||
// RETURNS: A pointer to the registered benchmark.
|
||||
internal::Benchmark* RegisterBenchmark(const char* name, internal::Function* fn);
|
||||
internal::Benchmark* RegisterBenchmark(const char* name,
|
||||
internal::Function* fn);
|
||||
|
||||
#if defined(BENCHMARK_HAS_CXX11)
|
||||
template <class Lambda>
|
||||
@@ -637,30 +655,30 @@ namespace internal {
|
||||
// The class used to hold all Benchmarks created from static function.
|
||||
// (ie those created using the BENCHMARK(...) macros.
|
||||
class FunctionBenchmark : public Benchmark {
|
||||
public:
|
||||
FunctionBenchmark(const char* name, Function* func)
|
||||
: Benchmark(name), func_(func)
|
||||
{}
|
||||
public:
|
||||
FunctionBenchmark(const char* name, Function* func)
|
||||
: Benchmark(name), func_(func) {}
|
||||
|
||||
virtual void Run(State& st);
|
||||
private:
|
||||
Function* func_;
|
||||
virtual void Run(State& st);
|
||||
|
||||
private:
|
||||
Function* func_;
|
||||
};
|
||||
|
||||
#ifdef BENCHMARK_HAS_CXX11
|
||||
template <class Lambda>
|
||||
class LambdaBenchmark : public Benchmark {
|
||||
public:
|
||||
virtual void Run(State& st) { lambda_(st); }
|
||||
public:
|
||||
virtual void Run(State& st) { lambda_(st); }
|
||||
|
||||
private:
|
||||
private:
|
||||
template <class OLambda>
|
||||
LambdaBenchmark(const char* name, OLambda&& lam)
|
||||
: Benchmark(name), lambda_(std::forward<OLambda>(lam)) {}
|
||||
|
||||
LambdaBenchmark(LambdaBenchmark const&) = delete;
|
||||
|
||||
private:
|
||||
private:
|
||||
template <class Lam>
|
||||
friend Benchmark* ::benchmark::RegisterBenchmark(const char*, Lam&&);
|
||||
|
||||
@@ -670,55 +688,58 @@ private:
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
inline internal::Benchmark*
|
||||
RegisterBenchmark(const char* name, internal::Function* fn) {
|
||||
return internal::RegisterBenchmarkInternal(
|
||||
::new internal::FunctionBenchmark(name, fn));
|
||||
inline internal::Benchmark* RegisterBenchmark(const char* name,
|
||||
internal::Function* fn) {
|
||||
return internal::RegisterBenchmarkInternal(
|
||||
::new internal::FunctionBenchmark(name, fn));
|
||||
}
|
||||
|
||||
#ifdef BENCHMARK_HAS_CXX11
|
||||
template <class Lambda>
|
||||
internal::Benchmark* RegisterBenchmark(const char* name, Lambda&& fn) {
|
||||
using BenchType = internal::LambdaBenchmark<typename std::decay<Lambda>::type>;
|
||||
return internal::RegisterBenchmarkInternal(
|
||||
::new BenchType(name, std::forward<Lambda>(fn)));
|
||||
using BenchType =
|
||||
internal::LambdaBenchmark<typename std::decay<Lambda>::type>;
|
||||
return internal::RegisterBenchmarkInternal(
|
||||
::new BenchType(name, std::forward<Lambda>(fn)));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(BENCHMARK_HAS_CXX11) && \
|
||||
(!defined(BENCHMARK_GCC_VERSION) || BENCHMARK_GCC_VERSION >= 409)
|
||||
template <class Lambda, class ...Args>
|
||||
(!defined(BENCHMARK_GCC_VERSION) || BENCHMARK_GCC_VERSION >= 409)
|
||||
template <class Lambda, class... Args>
|
||||
internal::Benchmark* RegisterBenchmark(const char* name, Lambda&& fn,
|
||||
Args&&... args) {
|
||||
return benchmark::RegisterBenchmark(name,
|
||||
[=](benchmark::State& st) { fn(st, args...); });
|
||||
return benchmark::RegisterBenchmark(
|
||||
name, [=](benchmark::State& st) { fn(st, args...); });
|
||||
}
|
||||
#else
|
||||
#define BENCHMARK_HAS_NO_VARIADIC_REGISTER_BENCHMARK
|
||||
#endif
|
||||
|
||||
|
||||
// The base class for all fixture tests.
|
||||
class Fixture: public internal::Benchmark {
|
||||
public:
|
||||
Fixture() : internal::Benchmark("") {}
|
||||
class Fixture : public internal::Benchmark {
|
||||
public:
|
||||
Fixture() : internal::Benchmark("") {}
|
||||
|
||||
virtual void Run(State& st) {
|
||||
this->SetUp(st);
|
||||
this->BenchmarkCase(st);
|
||||
this->TearDown(st);
|
||||
}
|
||||
virtual void Run(State& st) {
|
||||
this->SetUp(st);
|
||||
this->BenchmarkCase(st);
|
||||
this->TearDown(st);
|
||||
}
|
||||
|
||||
virtual void SetUp(const State&) {}
|
||||
virtual void TearDown(const State&) {}
|
||||
// These will be deprecated ...
|
||||
virtual void SetUp(const State&) {}
|
||||
virtual void TearDown(const State&) {}
|
||||
// ... In favor of these.
|
||||
virtual void SetUp(State& st) { SetUp(const_cast<const State&>(st)); }
|
||||
virtual void TearDown(State& st) { TearDown(const_cast<const State&>(st)); }
|
||||
|
||||
protected:
|
||||
virtual void BenchmarkCase(State&) = 0;
|
||||
protected:
|
||||
virtual void BenchmarkCase(State&) = 0;
|
||||
};
|
||||
|
||||
} // end namespace benchmark
|
||||
|
||||
|
||||
// ------------------------------------------------------
|
||||
// Macro to register benchmarks
|
||||
|
||||
@@ -733,18 +754,18 @@ protected:
|
||||
|
||||
// Helpers for generating unique variable names
|
||||
#define BENCHMARK_PRIVATE_NAME(n) \
|
||||
BENCHMARK_PRIVATE_CONCAT(_benchmark_, BENCHMARK_PRIVATE_UNIQUE_ID, n)
|
||||
BENCHMARK_PRIVATE_CONCAT(_benchmark_, BENCHMARK_PRIVATE_UNIQUE_ID, n)
|
||||
#define BENCHMARK_PRIVATE_CONCAT(a, b, c) BENCHMARK_PRIVATE_CONCAT2(a, b, c)
|
||||
#define BENCHMARK_PRIVATE_CONCAT2(a, b, c) a##b##c
|
||||
|
||||
#define BENCHMARK_PRIVATE_DECLARE(n) \
|
||||
static ::benchmark::internal::Benchmark* \
|
||||
BENCHMARK_PRIVATE_NAME(n) BENCHMARK_UNUSED
|
||||
#define BENCHMARK_PRIVATE_DECLARE(n) \
|
||||
static ::benchmark::internal::Benchmark* BENCHMARK_PRIVATE_NAME(n) \
|
||||
BENCHMARK_UNUSED
|
||||
|
||||
#define BENCHMARK(n) \
|
||||
BENCHMARK_PRIVATE_DECLARE(n) = \
|
||||
(::benchmark::internal::RegisterBenchmarkInternal( \
|
||||
new ::benchmark::internal::FunctionBenchmark(#n, n)))
|
||||
#define BENCHMARK(n) \
|
||||
BENCHMARK_PRIVATE_DECLARE(n) = \
|
||||
(::benchmark::internal::RegisterBenchmarkInternal( \
|
||||
new ::benchmark::internal::FunctionBenchmark(#n, n)))
|
||||
|
||||
// Old-style macros
|
||||
#define BENCHMARK_WITH_ARG(n, a) BENCHMARK(n)->Arg((a))
|
||||
@@ -767,14 +788,14 @@ protected:
|
||||
//}
|
||||
// /* Registers a benchmark named "BM_takes_args/int_string_test` */
|
||||
// BENCHMARK_CAPTURE(BM_takes_args, int_string_test, 42, std::string("abc"));
|
||||
#define BENCHMARK_CAPTURE(func, test_case_name, ...) \
|
||||
BENCHMARK_PRIVATE_DECLARE(func) = \
|
||||
(::benchmark::internal::RegisterBenchmarkInternal( \
|
||||
new ::benchmark::internal::FunctionBenchmark( \
|
||||
#func "/" #test_case_name, \
|
||||
[](::benchmark::State& st) { func(st, __VA_ARGS__); })))
|
||||
#define BENCHMARK_CAPTURE(func, test_case_name, ...) \
|
||||
BENCHMARK_PRIVATE_DECLARE(func) = \
|
||||
(::benchmark::internal::RegisterBenchmarkInternal( \
|
||||
new ::benchmark::internal::FunctionBenchmark( \
|
||||
#func "/" #test_case_name, \
|
||||
[](::benchmark::State& st) { func(st, __VA_ARGS__); })))
|
||||
|
||||
#endif // __cplusplus >= 11
|
||||
#endif // __cplusplus >= 11
|
||||
|
||||
// This will register a benchmark for a templatized function. For example:
|
||||
//
|
||||
@@ -784,54 +805,54 @@ protected:
|
||||
// BENCHMARK_TEMPLATE(BM_Foo, 1);
|
||||
//
|
||||
// will register BM_Foo<1> as a benchmark.
|
||||
#define BENCHMARK_TEMPLATE1(n, a) \
|
||||
BENCHMARK_PRIVATE_DECLARE(n) = \
|
||||
(::benchmark::internal::RegisterBenchmarkInternal( \
|
||||
new ::benchmark::internal::FunctionBenchmark(#n "<" #a ">", n<a>)))
|
||||
|
||||
#define BENCHMARK_TEMPLATE2(n, a, b) \
|
||||
#define BENCHMARK_TEMPLATE1(n, a) \
|
||||
BENCHMARK_PRIVATE_DECLARE(n) = \
|
||||
(::benchmark::internal::RegisterBenchmarkInternal( \
|
||||
new ::benchmark::internal::FunctionBenchmark( \
|
||||
#n "<" #a "," #b ">", n<a, b>)))
|
||||
new ::benchmark::internal::FunctionBenchmark(#n "<" #a ">", n<a>)))
|
||||
|
||||
#define BENCHMARK_TEMPLATE2(n, a, b) \
|
||||
BENCHMARK_PRIVATE_DECLARE(n) = \
|
||||
(::benchmark::internal::RegisterBenchmarkInternal( \
|
||||
new ::benchmark::internal::FunctionBenchmark(#n "<" #a "," #b ">", \
|
||||
n<a, b>)))
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
#define BENCHMARK_TEMPLATE(n, ...) \
|
||||
BENCHMARK_PRIVATE_DECLARE(n) = \
|
||||
#define BENCHMARK_TEMPLATE(n, ...) \
|
||||
BENCHMARK_PRIVATE_DECLARE(n) = \
|
||||
(::benchmark::internal::RegisterBenchmarkInternal( \
|
||||
new ::benchmark::internal::FunctionBenchmark( \
|
||||
#n "<" #__VA_ARGS__ ">", n<__VA_ARGS__>)))
|
||||
new ::benchmark::internal::FunctionBenchmark( \
|
||||
#n "<" #__VA_ARGS__ ">", n<__VA_ARGS__>)))
|
||||
#else
|
||||
#define BENCHMARK_TEMPLATE(n, a) BENCHMARK_TEMPLATE1(n, a)
|
||||
#endif
|
||||
|
||||
#define BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \
|
||||
class BaseClass##_##Method##_Benchmark : public BaseClass { \
|
||||
public: \
|
||||
BaseClass##_##Method##_Benchmark() : BaseClass() { \
|
||||
this->SetName(#BaseClass "/" #Method); \
|
||||
} \
|
||||
\
|
||||
protected: \
|
||||
virtual void BenchmarkCase(::benchmark::State&); \
|
||||
};
|
||||
|
||||
#define BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \
|
||||
class BaseClass##_##Method##_Benchmark : public BaseClass { \
|
||||
public: \
|
||||
BaseClass##_##Method##_Benchmark() : BaseClass() { \
|
||||
this->SetName(#BaseClass "/" #Method);} \
|
||||
protected: \
|
||||
virtual void BenchmarkCase(::benchmark::State&); \
|
||||
};
|
||||
|
||||
#define BENCHMARK_DEFINE_F(BaseClass, Method) \
|
||||
BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \
|
||||
void BaseClass##_##Method##_Benchmark::BenchmarkCase
|
||||
#define BENCHMARK_DEFINE_F(BaseClass, Method) \
|
||||
BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \
|
||||
void BaseClass##_##Method##_Benchmark::BenchmarkCase
|
||||
|
||||
#define BENCHMARK_REGISTER_F(BaseClass, Method) \
|
||||
BENCHMARK_PRIVATE_REGISTER_F(BaseClass##_##Method##_Benchmark)
|
||||
BENCHMARK_PRIVATE_REGISTER_F(BaseClass##_##Method##_Benchmark)
|
||||
|
||||
#define BENCHMARK_PRIVATE_REGISTER_F(TestName) \
|
||||
BENCHMARK_PRIVATE_DECLARE(TestName) = \
|
||||
(::benchmark::internal::RegisterBenchmarkInternal(new TestName()))
|
||||
BENCHMARK_PRIVATE_DECLARE(TestName) = \
|
||||
(::benchmark::internal::RegisterBenchmarkInternal(new TestName()))
|
||||
|
||||
// This macro will define and register a benchmark within a fixture class.
|
||||
#define BENCHMARK_F(BaseClass, Method) \
|
||||
BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \
|
||||
BENCHMARK_REGISTER_F(BaseClass, Method); \
|
||||
void BaseClass##_##Method##_Benchmark::BenchmarkCase
|
||||
|
||||
#define BENCHMARK_F(BaseClass, Method) \
|
||||
BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \
|
||||
BENCHMARK_REGISTER_F(BaseClass, Method); \
|
||||
void BaseClass##_##Method##_Benchmark::BenchmarkCase
|
||||
|
||||
// Helper macro to create a main routine in a test that runs the benchmarks
|
||||
#define BENCHMARK_MAIN() \
|
||||
|
||||
Reference in New Issue
Block a user