mirror of https://github.com/google/benchmark.git
Apply clang-format to all headers and source (#303)
This commit is contained in:
parent
1100e91907
commit
332f677b8b
|
@ -14,8 +14,8 @@
|
||||||
#ifndef BENCHMARK_BENCHMARK_H_
|
#ifndef BENCHMARK_BENCHMARK_H_
|
||||||
#define BENCHMARK_BENCHMARK_H_
|
#define BENCHMARK_BENCHMARK_H_
|
||||||
|
|
||||||
#include "macros.h"
|
|
||||||
#include "benchmark_api.h"
|
#include "benchmark_api.h"
|
||||||
|
#include "macros.h"
|
||||||
#include "reporter.h"
|
#include "reporter.h"
|
||||||
|
|
||||||
#endif // BENCHMARK_BENCHMARK_H_
|
#endif // BENCHMARK_BENCHMARK_H_
|
||||||
|
|
|
@ -153,8 +153,8 @@ BENCHMARK(BM_test)->Unit(benchmark::kMillisecond);
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "macros.h"
|
#include "macros.h"
|
||||||
|
|
||||||
|
@ -174,7 +174,8 @@ void Initialize(int* argc, char** argv);
|
||||||
// report the results.
|
// report the results.
|
||||||
//
|
//
|
||||||
// The second and third overload use the specified 'console_reporter' and
|
// 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
|
// by '--benchmark_output'. If '--benchmark_output' is not given the
|
||||||
// 'file_reporter' is ignored.
|
// 'file_reporter' is ignored.
|
||||||
//
|
//
|
||||||
|
@ -184,7 +185,6 @@ size_t RunSpecifiedBenchmarks(BenchmarkReporter* console_reporter);
|
||||||
size_t RunSpecifiedBenchmarks(BenchmarkReporter* console_reporter,
|
size_t RunSpecifiedBenchmarks(BenchmarkReporter* console_reporter,
|
||||||
BenchmarkReporter* file_reporter);
|
BenchmarkReporter* file_reporter);
|
||||||
|
|
||||||
|
|
||||||
// If this routine is called, peak memory allocation past this point in the
|
// 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
|
// 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
|
// computed by running the benchmark once with a single iteration and a memory
|
||||||
|
@ -197,8 +197,9 @@ class Benchmark;
|
||||||
class BenchmarkImp;
|
class BenchmarkImp;
|
||||||
class BenchmarkFamilies;
|
class BenchmarkFamilies;
|
||||||
|
|
||||||
template <class T> struct Voider {
|
template <class T>
|
||||||
typedef void type;
|
struct Voider {
|
||||||
|
typedef void type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T, class = void>
|
template <class T, class = void>
|
||||||
|
@ -206,7 +207,7 @@ struct EnableIfString {};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
struct EnableIfString<T, typename Voider<typename T::basic_string>::type> {
|
struct EnableIfString<T, typename Voider<typename T::basic_string>::type> {
|
||||||
typedef int type;
|
typedef int type;
|
||||||
};
|
};
|
||||||
|
|
||||||
void UseCharPointer(char const volatile*);
|
void UseCharPointer(char const volatile*);
|
||||||
|
@ -219,8 +220,7 @@ Benchmark* RegisterBenchmarkInternal(Benchmark*);
|
||||||
int InitializeStreams();
|
int InitializeStreams();
|
||||||
BENCHMARK_UNUSED static int stream_init_anchor = 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
|
// The DoNotOptimize(...) function can be used to prevent a value or
|
||||||
// expression from being optimized away by the compiler. This function is
|
// expression from being optimized away by the compiler. This function is
|
||||||
|
@ -229,45 +229,32 @@ BENCHMARK_UNUSED static int stream_init_anchor = InitializeStreams();
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
template <class Tp>
|
template <class Tp>
|
||||||
inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) {
|
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
|
// Force the compiler to flush pending writes to global memory. Acts as an
|
||||||
// effective read/write barrier
|
// effective read/write barrier
|
||||||
inline BENCHMARK_ALWAYS_INLINE void ClobberMemory() {
|
inline BENCHMARK_ALWAYS_INLINE void ClobberMemory() {
|
||||||
asm volatile("" : : : "memory");
|
asm volatile("" : : : "memory");
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
template <class Tp>
|
template <class Tp>
|
||||||
inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) {
|
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
|
// FIXME Add ClobberMemory() for non-gnu compilers
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// TimeUnit is passed to a benchmark in order to specify the order of magnitude
|
// TimeUnit is passed to a benchmark in order to specify the order of magnitude
|
||||||
// for the measured time.
|
// for the measured time.
|
||||||
enum TimeUnit {
|
enum TimeUnit { kNanosecond, kMicrosecond, kMillisecond };
|
||||||
kNanosecond,
|
|
||||||
kMicrosecond,
|
|
||||||
kMillisecond
|
|
||||||
};
|
|
||||||
|
|
||||||
// BigO is passed to a benchmark in order to specify the asymptotic computational
|
// BigO is passed to a benchmark in order to specify the asymptotic
|
||||||
// complexity for the benchmark. In case oAuto is selected, complexity will be
|
// computational
|
||||||
|
// complexity for the benchmark. In case oAuto is selected, complexity will be
|
||||||
// calculated automatically to the best fit.
|
// calculated automatically to the best fit.
|
||||||
enum BigO {
|
enum BigO { oNone, o1, oN, oNSquared, oNCubed, oLogN, oNLogN, oAuto, oLambda };
|
||||||
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.
|
// computational complexity for the benchmark.
|
||||||
typedef double(BigOFunc)(int);
|
typedef double(BigOFunc)(int);
|
||||||
|
|
||||||
|
@ -280,17 +267,16 @@ enum ReportMode : unsigned {
|
||||||
#else
|
#else
|
||||||
enum ReportMode {
|
enum ReportMode {
|
||||||
#endif
|
#endif
|
||||||
RM_Unspecified, // The mode has not been manually specified
|
RM_Unspecified, // The mode has not been manually specified
|
||||||
RM_Default, // The mode is user-specified as default.
|
RM_Default, // The mode is user-specified as default.
|
||||||
RM_ReportAggregatesOnly
|
RM_ReportAggregatesOnly
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// State is passed to a running Benchmark and contains state for the
|
// State is passed to a running Benchmark and contains state for the
|
||||||
// benchmark to use.
|
// benchmark to use.
|
||||||
class State {
|
class State {
|
||||||
public:
|
public:
|
||||||
// Returns true if the benchmark should continue through another iteration.
|
// Returns true if the benchmark should continue through another iteration.
|
||||||
// NOTE: A benchmark may not return from the test until KeepRunning() has
|
// NOTE: A benchmark may not return from the test until KeepRunning() has
|
||||||
// returned false.
|
// returned false.
|
||||||
|
@ -365,27 +351,21 @@ public:
|
||||||
//
|
//
|
||||||
// REQUIRES: a benchmark has exited its KeepRunning loop.
|
// REQUIRES: a benchmark has exited its KeepRunning loop.
|
||||||
BENCHMARK_ALWAYS_INLINE
|
BENCHMARK_ALWAYS_INLINE
|
||||||
void SetBytesProcessed(size_t bytes) {
|
void SetBytesProcessed(size_t bytes) { bytes_processed_ = bytes; }
|
||||||
bytes_processed_ = bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
BENCHMARK_ALWAYS_INLINE
|
BENCHMARK_ALWAYS_INLINE
|
||||||
size_t bytes_processed() const {
|
size_t bytes_processed() const { return bytes_processed_; }
|
||||||
return bytes_processed_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If this routine is called with complexity_n > 0 and complexity report is requested for the
|
// If this routine is called with complexity_n > 0 and complexity report is
|
||||||
// family benchmark, then current benchmark will be part of the computation and complexity_n will
|
// requested for the
|
||||||
|
// family benchmark, then current benchmark will be part of the computation
|
||||||
|
// and complexity_n will
|
||||||
// represent the length of N.
|
// represent the length of N.
|
||||||
BENCHMARK_ALWAYS_INLINE
|
BENCHMARK_ALWAYS_INLINE
|
||||||
void SetComplexityN(int complexity_n) {
|
void SetComplexityN(int complexity_n) { complexity_n_ = complexity_n; }
|
||||||
complexity_n_ = complexity_n;
|
|
||||||
}
|
|
||||||
|
|
||||||
BENCHMARK_ALWAYS_INLINE
|
BENCHMARK_ALWAYS_INLINE
|
||||||
int complexity_length_n() {
|
int complexity_length_n() { return complexity_n_; }
|
||||||
return complexity_n_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If this routine is called with items > 0, then an items/s
|
// If this routine is called with items > 0, then an items/s
|
||||||
// label is printed on the benchmark report line for the currently
|
// label is printed on the benchmark report line for the currently
|
||||||
|
@ -394,14 +374,10 @@ public:
|
||||||
//
|
//
|
||||||
// REQUIRES: a benchmark has exited its KeepRunning loop.
|
// REQUIRES: a benchmark has exited its KeepRunning loop.
|
||||||
BENCHMARK_ALWAYS_INLINE
|
BENCHMARK_ALWAYS_INLINE
|
||||||
void SetItemsProcessed(size_t items) {
|
void SetItemsProcessed(size_t items) { items_processed_ = items; }
|
||||||
items_processed_ = items;
|
|
||||||
}
|
|
||||||
|
|
||||||
BENCHMARK_ALWAYS_INLINE
|
BENCHMARK_ALWAYS_INLINE
|
||||||
size_t items_processed() const {
|
size_t items_processed() const { return items_processed_; }
|
||||||
return items_processed_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If this routine is called, the specified label is printed at the
|
// If this routine is called, the specified label is printed at the
|
||||||
// end of the benchmark report line for the currently executing
|
// 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
|
// has the nested typename `basic_string`. This typename should be provided
|
||||||
// as an injected class name in the case of std::string.
|
// as an injected class name in the case of std::string.
|
||||||
template <class StringType>
|
template <class StringType>
|
||||||
void SetLabel(StringType const & str,
|
void SetLabel(StringType const& str,
|
||||||
typename internal::EnableIfString<StringType>::type = 1) {
|
typename internal::EnableIfString<StringType>::type = 1) {
|
||||||
this->SetLabel(str.c_str());
|
this->SetLabel(str.c_str());
|
||||||
}
|
}
|
||||||
|
@ -430,8 +406,8 @@ public:
|
||||||
// Range arguments for this run. CHECKs if the argument has been set.
|
// Range arguments for this run. CHECKs if the argument has been set.
|
||||||
BENCHMARK_ALWAYS_INLINE
|
BENCHMARK_ALWAYS_INLINE
|
||||||
int range(std::size_t pos = 0) const {
|
int range(std::size_t pos = 0) const {
|
||||||
assert(range_.size() > pos);
|
assert(range_.size() > pos);
|
||||||
return range_[pos];
|
return range_[pos];
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCHMARK_DEPRECATED_MSG("use 'range(0)' instead")
|
BENCHMARK_DEPRECATED_MSG("use 'range(0)' instead")
|
||||||
|
@ -443,7 +419,7 @@ public:
|
||||||
BENCHMARK_ALWAYS_INLINE
|
BENCHMARK_ALWAYS_INLINE
|
||||||
size_t iterations() const { return total_iterations_; }
|
size_t iterations() const { return total_iterations_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool started_;
|
bool started_;
|
||||||
bool finished_;
|
bool finished_;
|
||||||
size_t total_iterations_;
|
size_t total_iterations_;
|
||||||
|
@ -455,10 +431,11 @@ private:
|
||||||
|
|
||||||
int complexity_n_;
|
int complexity_n_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// FIXME: Make this private somehow.
|
// FIXME: Make this private somehow.
|
||||||
bool error_occurred_;
|
bool error_occurred_;
|
||||||
public:
|
|
||||||
|
public:
|
||||||
// Index of the executing thread. Values from [0, threads).
|
// Index of the executing thread. Values from [0, threads).
|
||||||
const int thread_index;
|
const int thread_index;
|
||||||
// Number of threads concurrently executing the benchmark.
|
// Number of threads concurrently executing the benchmark.
|
||||||
|
@ -489,7 +466,7 @@ typedef void(Function)(State&);
|
||||||
// Each method returns "this" so that multiple method calls can
|
// Each method returns "this" so that multiple method calls can
|
||||||
// chained into one expression.
|
// chained into one expression.
|
||||||
class Benchmark {
|
class Benchmark {
|
||||||
public:
|
public:
|
||||||
virtual ~Benchmark();
|
virtual ~Benchmark();
|
||||||
|
|
||||||
// Note: the following methods all return "this" so that multiple
|
// Note: the following methods all return "this" so that multiple
|
||||||
|
@ -508,7 +485,8 @@ public:
|
||||||
// REQUIRES: The function passed to the constructor must accept an arg1.
|
// REQUIRES: The function passed to the constructor must accept an arg1.
|
||||||
Benchmark* Range(int start, int limit);
|
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.
|
// REQUIRES: The function passed to the constructor must accept an arg1.
|
||||||
Benchmark* DenseRange(int start, int limit, int step = 1);
|
Benchmark* DenseRange(int start, int limit, int step = 1);
|
||||||
|
|
||||||
|
@ -521,10 +499,10 @@ public:
|
||||||
// NOTE: This is a legacy C++03 interface provided for compatibility only.
|
// NOTE: This is a legacy C++03 interface provided for compatibility only.
|
||||||
// New code should use 'Args'.
|
// New code should use 'Args'.
|
||||||
Benchmark* ArgPair(int x, int y) {
|
Benchmark* ArgPair(int x, int y) {
|
||||||
std::vector<int> args;
|
std::vector<int> args;
|
||||||
args.push_back(x);
|
args.push_back(x);
|
||||||
args.push_back(y);
|
args.push_back(y);
|
||||||
return Args(args);
|
return Args(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run this benchmark once for a number of values picked from the
|
// Run this benchmark once for a number of values picked from the
|
||||||
|
@ -536,10 +514,10 @@ public:
|
||||||
// NOTE: This is a legacy C++03 interface provided for compatibility only.
|
// NOTE: This is a legacy C++03 interface provided for compatibility only.
|
||||||
// New code should use 'Ranges'.
|
// New code should use 'Ranges'.
|
||||||
Benchmark* RangePair(int lo1, int hi1, int lo2, int hi2) {
|
Benchmark* RangePair(int lo1, int hi1, int lo2, int hi2) {
|
||||||
std::vector<std::pair<int, int> > ranges;
|
std::vector<std::pair<int, int> > ranges;
|
||||||
ranges.push_back(std::make_pair(lo1, hi1));
|
ranges.push_back(std::make_pair(lo1, hi1));
|
||||||
ranges.push_back(std::make_pair(lo2, hi2));
|
ranges.push_back(std::make_pair(lo2, hi2));
|
||||||
return Ranges(ranges);
|
return Ranges(ranges);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pass this benchmark object to *func, which can customize
|
// Pass this benchmark object to *func, which can customize
|
||||||
|
@ -547,7 +525,8 @@ public:
|
||||||
// Threads, etc.
|
// Threads, etc.
|
||||||
Benchmark* Apply(void (*func)(Benchmark* benchmark));
|
Benchmark* Apply(void (*func)(Benchmark* benchmark));
|
||||||
|
|
||||||
// Set the range multiplier for non-dense range. If not called, the range multiplier
|
// Set the range multiplier for non-dense range. If not called, the range
|
||||||
|
// multiplier
|
||||||
// kRangeMultiplier will be used.
|
// kRangeMultiplier will be used.
|
||||||
Benchmark* RangeMultiplier(int multiplier);
|
Benchmark* RangeMultiplier(int multiplier);
|
||||||
|
|
||||||
|
@ -573,15 +552,17 @@ public:
|
||||||
// called, the cpu time used by the benchmark will be used.
|
// called, the cpu time used by the benchmark will be used.
|
||||||
Benchmark* UseRealTime();
|
Benchmark* UseRealTime();
|
||||||
|
|
||||||
// If a benchmark must measure time manually (e.g. if GPU execution time is being
|
// If a benchmark must measure time manually (e.g. if GPU execution time is
|
||||||
// measured), call this method. If called, each benchmark iteration should call
|
// being
|
||||||
|
// measured), call this method. If called, each benchmark iteration should
|
||||||
|
// call
|
||||||
// SetIterationTime(seconds) to report the measured time, which will be used
|
// 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
|
// to control how many iterations are run, and in the printing of items/second
|
||||||
// or MB/second values.
|
// or MB/second values.
|
||||||
Benchmark* UseManualTime();
|
Benchmark* UseManualTime();
|
||||||
|
|
||||||
// Set the asymptotic computational complexity for the benchmark. If called
|
// 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);
|
Benchmark* Complexity(BigO complexity = benchmark::oAuto);
|
||||||
|
|
||||||
// Set the asymptotic computational complexity for the benchmark. If called
|
// Set the asymptotic computational complexity for the benchmark. If called
|
||||||
|
@ -607,13 +588,13 @@ public:
|
||||||
// Foo in 4 threads
|
// Foo in 4 threads
|
||||||
// Foo in 8 threads
|
// Foo in 8 threads
|
||||||
// Foo in 16 threads
|
// Foo in 16 threads
|
||||||
Benchmark *ThreadRange(int min_threads, int max_threads);
|
Benchmark* ThreadRange(int min_threads, int max_threads);
|
||||||
|
|
||||||
// For each value n in the range, run this benchmark once using n 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.
|
// min_threads and max_threads are always included in the range.
|
||||||
// stride specifies the increment. E.g. DenseThreadRange(1, 8, 3) starts
|
// stride specifies the increment. E.g. DenseThreadRange(1, 8, 3) starts
|
||||||
// a benchmark with 1, 4, 7 and 8 threads.
|
// a benchmark with 1, 4, 7 and 8 threads.
|
||||||
Benchmark *DenseThreadRange(int min_threads, int max_threads, int stride = 1);
|
Benchmark* DenseThreadRange(int min_threads, int max_threads, int stride = 1);
|
||||||
|
|
||||||
// Equivalent to ThreadRange(NumCPUs(), NumCPUs())
|
// Equivalent to ThreadRange(NumCPUs(), NumCPUs())
|
||||||
Benchmark* ThreadPerCpu();
|
Benchmark* ThreadPerCpu();
|
||||||
|
@ -623,7 +604,7 @@ public:
|
||||||
// Used inside the benchmark implementation
|
// Used inside the benchmark implementation
|
||||||
struct Instance;
|
struct Instance;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
explicit Benchmark(const char* name);
|
explicit Benchmark(const char* name);
|
||||||
Benchmark(Benchmark const&);
|
Benchmark(Benchmark const&);
|
||||||
void SetName(const char* name);
|
void SetName(const char* name);
|
||||||
|
@ -632,12 +613,12 @@ protected:
|
||||||
|
|
||||||
static void AddRange(std::vector<int>* dst, int lo, int hi, int mult);
|
static void AddRange(std::vector<int>* dst, int lo, int hi, int mult);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class BenchmarkFamilies;
|
friend class BenchmarkFamilies;
|
||||||
|
|
||||||
std::string name_;
|
std::string name_;
|
||||||
ReportMode report_mode_;
|
ReportMode report_mode_;
|
||||||
std::vector< std::vector<int> > args_; // Args for all benchmark runs
|
std::vector<std::vector<int> > args_; // Args for all benchmark runs
|
||||||
TimeUnit time_unit_;
|
TimeUnit time_unit_;
|
||||||
int range_multiplier_;
|
int range_multiplier_;
|
||||||
double min_time_;
|
double min_time_;
|
||||||
|
@ -651,13 +632,14 @@ private:
|
||||||
Benchmark& operator=(Benchmark const&);
|
Benchmark& operator=(Benchmark const&);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
// Create and register a benchmark with the specified 'name' that invokes
|
// Create and register a benchmark with the specified 'name' that invokes
|
||||||
// the specified functor 'fn'.
|
// the specified functor 'fn'.
|
||||||
//
|
//
|
||||||
// RETURNS: A pointer to the registered benchmark.
|
// 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)
|
#if defined(BENCHMARK_HAS_CXX11)
|
||||||
template <class Lambda>
|
template <class Lambda>
|
||||||
|
@ -668,30 +650,30 @@ namespace internal {
|
||||||
// The class used to hold all Benchmarks created from static function.
|
// The class used to hold all Benchmarks created from static function.
|
||||||
// (ie those created using the BENCHMARK(...) macros.
|
// (ie those created using the BENCHMARK(...) macros.
|
||||||
class FunctionBenchmark : public Benchmark {
|
class FunctionBenchmark : public Benchmark {
|
||||||
public:
|
public:
|
||||||
FunctionBenchmark(const char* name, Function* func)
|
FunctionBenchmark(const char* name, Function* func)
|
||||||
: Benchmark(name), func_(func)
|
: Benchmark(name), func_(func) {}
|
||||||
{}
|
|
||||||
|
|
||||||
virtual void Run(State& st);
|
virtual void Run(State& st);
|
||||||
private:
|
|
||||||
Function* func_;
|
private:
|
||||||
|
Function* func_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef BENCHMARK_HAS_CXX11
|
#ifdef BENCHMARK_HAS_CXX11
|
||||||
template <class Lambda>
|
template <class Lambda>
|
||||||
class LambdaBenchmark : public Benchmark {
|
class LambdaBenchmark : public Benchmark {
|
||||||
public:
|
public:
|
||||||
virtual void Run(State& st) { lambda_(st); }
|
virtual void Run(State& st) { lambda_(st); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <class OLambda>
|
template <class OLambda>
|
||||||
LambdaBenchmark(const char* name, OLambda&& lam)
|
LambdaBenchmark(const char* name, OLambda&& lam)
|
||||||
: Benchmark(name), lambda_(std::forward<OLambda>(lam)) {}
|
: Benchmark(name), lambda_(std::forward<OLambda>(lam)) {}
|
||||||
|
|
||||||
LambdaBenchmark(LambdaBenchmark const&) = delete;
|
LambdaBenchmark(LambdaBenchmark const&) = delete;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <class Lam>
|
template <class Lam>
|
||||||
friend Benchmark* ::benchmark::RegisterBenchmark(const char*, Lam&&);
|
friend Benchmark* ::benchmark::RegisterBenchmark(const char*, Lam&&);
|
||||||
|
|
||||||
|
@ -701,59 +683,58 @@ private:
|
||||||
|
|
||||||
} // end namespace internal
|
} // end namespace internal
|
||||||
|
|
||||||
inline internal::Benchmark*
|
inline internal::Benchmark* RegisterBenchmark(const char* name,
|
||||||
RegisterBenchmark(const char* name, internal::Function* fn) {
|
internal::Function* fn) {
|
||||||
return internal::RegisterBenchmarkInternal(
|
return internal::RegisterBenchmarkInternal(
|
||||||
::new internal::FunctionBenchmark(name, fn));
|
::new internal::FunctionBenchmark(name, fn));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef BENCHMARK_HAS_CXX11
|
#ifdef BENCHMARK_HAS_CXX11
|
||||||
template <class Lambda>
|
template <class Lambda>
|
||||||
internal::Benchmark* RegisterBenchmark(const char* name, Lambda&& fn) {
|
internal::Benchmark* RegisterBenchmark(const char* name, Lambda&& fn) {
|
||||||
using BenchType = internal::LambdaBenchmark<typename std::decay<Lambda>::type>;
|
using BenchType =
|
||||||
return internal::RegisterBenchmarkInternal(
|
internal::LambdaBenchmark<typename std::decay<Lambda>::type>;
|
||||||
::new BenchType(name, std::forward<Lambda>(fn)));
|
return internal::RegisterBenchmarkInternal(
|
||||||
|
::new BenchType(name, std::forward<Lambda>(fn)));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(BENCHMARK_HAS_CXX11) && \
|
#if defined(BENCHMARK_HAS_CXX11) && \
|
||||||
(!defined(BENCHMARK_GCC_VERSION) || BENCHMARK_GCC_VERSION >= 409)
|
(!defined(BENCHMARK_GCC_VERSION) || BENCHMARK_GCC_VERSION >= 409)
|
||||||
template <class Lambda, class ...Args>
|
template <class Lambda, class... Args>
|
||||||
internal::Benchmark* RegisterBenchmark(const char* name, Lambda&& fn,
|
internal::Benchmark* RegisterBenchmark(const char* name, Lambda&& fn,
|
||||||
Args&&... args) {
|
Args&&... args) {
|
||||||
return benchmark::RegisterBenchmark(name,
|
return benchmark::RegisterBenchmark(
|
||||||
[=](benchmark::State& st) { fn(st, args...); });
|
name, [=](benchmark::State& st) { fn(st, args...); });
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define BENCHMARK_HAS_NO_VARIADIC_REGISTER_BENCHMARK
|
#define BENCHMARK_HAS_NO_VARIADIC_REGISTER_BENCHMARK
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// The base class for all fixture tests.
|
// The base class for all fixture tests.
|
||||||
class Fixture: public internal::Benchmark {
|
class Fixture : public internal::Benchmark {
|
||||||
public:
|
public:
|
||||||
Fixture() : internal::Benchmark("") {}
|
Fixture() : internal::Benchmark("") {}
|
||||||
|
|
||||||
virtual void Run(State& st) {
|
virtual void Run(State& st) {
|
||||||
this->SetUp(st);
|
this->SetUp(st);
|
||||||
this->BenchmarkCase(st);
|
this->BenchmarkCase(st);
|
||||||
this->TearDown(st);
|
this->TearDown(st);
|
||||||
}
|
}
|
||||||
|
|
||||||
// These will be deprecated ...
|
// These will be deprecated ...
|
||||||
virtual void SetUp(const State&) {}
|
virtual void SetUp(const State&) {}
|
||||||
virtual void TearDown(const State&) {}
|
virtual void TearDown(const State&) {}
|
||||||
// ... In favor of these.
|
// ... In favor of these.
|
||||||
virtual void SetUp(State& st) { SetUp(const_cast<const State&>(st)); }
|
virtual void SetUp(State& st) { SetUp(const_cast<const State&>(st)); }
|
||||||
virtual void TearDown(State& st) { TearDown(const_cast<const State&>(st)); }
|
virtual void TearDown(State& st) { TearDown(const_cast<const State&>(st)); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void BenchmarkCase(State&) = 0;
|
virtual void BenchmarkCase(State&) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace benchmark
|
} // end namespace benchmark
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
// Macro to register benchmarks
|
// Macro to register benchmarks
|
||||||
|
|
||||||
|
@ -768,18 +749,18 @@ protected:
|
||||||
|
|
||||||
// Helpers for generating unique variable names
|
// Helpers for generating unique variable names
|
||||||
#define BENCHMARK_PRIVATE_NAME(n) \
|
#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_CONCAT(a, b, c) BENCHMARK_PRIVATE_CONCAT2(a, b, c)
|
||||||
#define BENCHMARK_PRIVATE_CONCAT2(a, b, c) a##b##c
|
#define BENCHMARK_PRIVATE_CONCAT2(a, b, c) a##b##c
|
||||||
|
|
||||||
#define BENCHMARK_PRIVATE_DECLARE(n) \
|
#define BENCHMARK_PRIVATE_DECLARE(n) \
|
||||||
static ::benchmark::internal::Benchmark* \
|
static ::benchmark::internal::Benchmark* BENCHMARK_PRIVATE_NAME(n) \
|
||||||
BENCHMARK_PRIVATE_NAME(n) BENCHMARK_UNUSED
|
BENCHMARK_UNUSED
|
||||||
|
|
||||||
#define BENCHMARK(n) \
|
#define BENCHMARK(n) \
|
||||||
BENCHMARK_PRIVATE_DECLARE(n) = \
|
BENCHMARK_PRIVATE_DECLARE(n) = \
|
||||||
(::benchmark::internal::RegisterBenchmarkInternal( \
|
(::benchmark::internal::RegisterBenchmarkInternal( \
|
||||||
new ::benchmark::internal::FunctionBenchmark(#n, n)))
|
new ::benchmark::internal::FunctionBenchmark(#n, n)))
|
||||||
|
|
||||||
// Old-style macros
|
// Old-style macros
|
||||||
#define BENCHMARK_WITH_ARG(n, a) BENCHMARK(n)->Arg((a))
|
#define BENCHMARK_WITH_ARG(n, a) BENCHMARK(n)->Arg((a))
|
||||||
|
@ -802,14 +783,14 @@ protected:
|
||||||
//}
|
//}
|
||||||
// /* Registers a benchmark named "BM_takes_args/int_string_test` */
|
// /* Registers a benchmark named "BM_takes_args/int_string_test` */
|
||||||
// BENCHMARK_CAPTURE(BM_takes_args, int_string_test, 42, std::string("abc"));
|
// BENCHMARK_CAPTURE(BM_takes_args, int_string_test, 42, std::string("abc"));
|
||||||
#define BENCHMARK_CAPTURE(func, test_case_name, ...) \
|
#define BENCHMARK_CAPTURE(func, test_case_name, ...) \
|
||||||
BENCHMARK_PRIVATE_DECLARE(func) = \
|
BENCHMARK_PRIVATE_DECLARE(func) = \
|
||||||
(::benchmark::internal::RegisterBenchmarkInternal( \
|
(::benchmark::internal::RegisterBenchmarkInternal( \
|
||||||
new ::benchmark::internal::FunctionBenchmark( \
|
new ::benchmark::internal::FunctionBenchmark( \
|
||||||
#func "/" #test_case_name, \
|
#func "/" #test_case_name, \
|
||||||
[](::benchmark::State& st) { func(st, __VA_ARGS__); })))
|
[](::benchmark::State& st) { func(st, __VA_ARGS__); })))
|
||||||
|
|
||||||
#endif // __cplusplus >= 11
|
#endif // __cplusplus >= 11
|
||||||
|
|
||||||
// This will register a benchmark for a templatized function. For example:
|
// This will register a benchmark for a templatized function. For example:
|
||||||
//
|
//
|
||||||
|
@ -819,54 +800,54 @@ protected:
|
||||||
// BENCHMARK_TEMPLATE(BM_Foo, 1);
|
// BENCHMARK_TEMPLATE(BM_Foo, 1);
|
||||||
//
|
//
|
||||||
// will register BM_Foo<1> as a benchmark.
|
// will register BM_Foo<1> as a benchmark.
|
||||||
#define BENCHMARK_TEMPLATE1(n, a) \
|
#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) \
|
|
||||||
BENCHMARK_PRIVATE_DECLARE(n) = \
|
BENCHMARK_PRIVATE_DECLARE(n) = \
|
||||||
(::benchmark::internal::RegisterBenchmarkInternal( \
|
(::benchmark::internal::RegisterBenchmarkInternal( \
|
||||||
new ::benchmark::internal::FunctionBenchmark( \
|
new ::benchmark::internal::FunctionBenchmark(#n "<" #a ">", n<a>)))
|
||||||
#n "<" #a "," #b ">", n<a, b>)))
|
|
||||||
|
#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
|
#if __cplusplus >= 201103L
|
||||||
#define BENCHMARK_TEMPLATE(n, ...) \
|
#define BENCHMARK_TEMPLATE(n, ...) \
|
||||||
BENCHMARK_PRIVATE_DECLARE(n) = \
|
BENCHMARK_PRIVATE_DECLARE(n) = \
|
||||||
(::benchmark::internal::RegisterBenchmarkInternal( \
|
(::benchmark::internal::RegisterBenchmarkInternal( \
|
||||||
new ::benchmark::internal::FunctionBenchmark( \
|
new ::benchmark::internal::FunctionBenchmark( \
|
||||||
#n "<" #__VA_ARGS__ ">", n<__VA_ARGS__>)))
|
#n "<" #__VA_ARGS__ ">", n<__VA_ARGS__>)))
|
||||||
#else
|
#else
|
||||||
#define BENCHMARK_TEMPLATE(n, a) BENCHMARK_TEMPLATE1(n, a)
|
#define BENCHMARK_TEMPLATE(n, a) BENCHMARK_TEMPLATE1(n, a)
|
||||||
#endif
|
#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) \
|
#define BENCHMARK_DEFINE_F(BaseClass, Method) \
|
||||||
class BaseClass##_##Method##_Benchmark : public BaseClass { \
|
BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \
|
||||||
public: \
|
void BaseClass##_##Method##_Benchmark::BenchmarkCase
|
||||||
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_REGISTER_F(BaseClass, Method) \
|
#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) \
|
#define BENCHMARK_PRIVATE_REGISTER_F(TestName) \
|
||||||
BENCHMARK_PRIVATE_DECLARE(TestName) = \
|
BENCHMARK_PRIVATE_DECLARE(TestName) = \
|
||||||
(::benchmark::internal::RegisterBenchmarkInternal(new TestName()))
|
(::benchmark::internal::RegisterBenchmarkInternal(new TestName()))
|
||||||
|
|
||||||
// This macro will define and register a benchmark within a fixture class.
|
// This macro will define and register a benchmark within a fixture class.
|
||||||
#define BENCHMARK_F(BaseClass, Method) \
|
#define BENCHMARK_F(BaseClass, Method) \
|
||||||
BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \
|
BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \
|
||||||
BENCHMARK_REGISTER_F(BaseClass, Method); \
|
BENCHMARK_REGISTER_F(BaseClass, Method); \
|
||||||
void BaseClass##_##Method##_Benchmark::BenchmarkCase
|
void BaseClass##_##Method##_Benchmark::BenchmarkCase
|
||||||
|
|
||||||
|
|
||||||
// Helper macro to create a main routine in a test that runs the benchmarks
|
// Helper macro to create a main routine in a test that runs the benchmarks
|
||||||
#define BENCHMARK_MAIN() \
|
#define BENCHMARK_MAIN() \
|
||||||
|
|
|
@ -19,44 +19,44 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef BENCHMARK_HAS_CXX11
|
#ifndef BENCHMARK_HAS_CXX11
|
||||||
# define BENCHMARK_DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
#define BENCHMARK_DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
||||||
TypeName(const TypeName&); \
|
TypeName(const TypeName&); \
|
||||||
TypeName& operator=(const TypeName&)
|
TypeName& operator=(const TypeName&)
|
||||||
#else
|
#else
|
||||||
# define BENCHMARK_DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
#define BENCHMARK_DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
||||||
TypeName(const TypeName&) = delete; \
|
TypeName(const TypeName&) = delete; \
|
||||||
TypeName& operator=(const TypeName&) = delete
|
TypeName& operator=(const TypeName&) = delete
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
# define BENCHMARK_UNUSED __attribute__((unused))
|
#define BENCHMARK_UNUSED __attribute__((unused))
|
||||||
# define BENCHMARK_ALWAYS_INLINE __attribute__((always_inline))
|
#define BENCHMARK_ALWAYS_INLINE __attribute__((always_inline))
|
||||||
# define BENCHMARK_NOEXCEPT noexcept
|
#define BENCHMARK_NOEXCEPT noexcept
|
||||||
# define BENCHMARK_NOEXCEPT_OP(x) noexcept(x)
|
#define BENCHMARK_NOEXCEPT_OP(x) noexcept(x)
|
||||||
#elif defined(_MSC_VER) && !defined(__clang__)
|
#elif defined(_MSC_VER) && !defined(__clang__)
|
||||||
# define BENCHMARK_UNUSED
|
#define BENCHMARK_UNUSED
|
||||||
# define BENCHMARK_ALWAYS_INLINE __forceinline
|
#define BENCHMARK_ALWAYS_INLINE __forceinline
|
||||||
# if _MSC_VER >= 1900
|
#if _MSC_VER >= 1900
|
||||||
# define BENCHMARK_NOEXCEPT noexcept
|
#define BENCHMARK_NOEXCEPT noexcept
|
||||||
# define BENCHMARK_NOEXCEPT_OP(x) noexcept(x)
|
#define BENCHMARK_NOEXCEPT_OP(x) noexcept(x)
|
||||||
# else
|
|
||||||
# define BENCHMARK_NOEXCEPT
|
|
||||||
# define BENCHMARK_NOEXCEPT_OP(x)
|
|
||||||
# endif
|
|
||||||
# define __func__ __FUNCTION__
|
|
||||||
#else
|
#else
|
||||||
# define BENCHMARK_UNUSED
|
#define BENCHMARK_NOEXCEPT
|
||||||
# define BENCHMARK_ALWAYS_INLINE
|
#define BENCHMARK_NOEXCEPT_OP(x)
|
||||||
# define BENCHMARK_NOEXCEPT
|
#endif
|
||||||
# define BENCHMARK_NOEXCEPT_OP(x)
|
#define __func__ __FUNCTION__
|
||||||
|
#else
|
||||||
|
#define BENCHMARK_UNUSED
|
||||||
|
#define BENCHMARK_ALWAYS_INLINE
|
||||||
|
#define BENCHMARK_NOEXCEPT
|
||||||
|
#define BENCHMARK_NOEXCEPT_OP(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
# define BENCHMARK_BUILTIN_EXPECT(x, y) __builtin_expect(x, y)
|
#define BENCHMARK_BUILTIN_EXPECT(x, y) __builtin_expect(x, y)
|
||||||
# define BENCHMARK_DEPRECATED_MSG(msg) __attribute__((deprecated(msg)))
|
#define BENCHMARK_DEPRECATED_MSG(msg) __attribute__((deprecated(msg)))
|
||||||
#else
|
#else
|
||||||
# define BENCHMARK_BUILTIN_EXPECT(x, y) x
|
#define BENCHMARK_BUILTIN_EXPECT(x, y) x
|
||||||
# define BENCHMARK_DEPRECATED_MSG(msg)
|
#define BENCHMARK_DEPRECATED_MSG(msg)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__GNUC__) && !defined(__clang__)
|
#if defined(__GNUC__) && !defined(__clang__)
|
||||||
|
|
|
@ -41,20 +41,20 @@ class BenchmarkReporter {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Run {
|
struct Run {
|
||||||
Run() :
|
Run()
|
||||||
error_occurred(false),
|
: error_occurred(false),
|
||||||
iterations(1),
|
iterations(1),
|
||||||
time_unit(kNanosecond),
|
time_unit(kNanosecond),
|
||||||
real_accumulated_time(0),
|
real_accumulated_time(0),
|
||||||
cpu_accumulated_time(0),
|
cpu_accumulated_time(0),
|
||||||
bytes_per_second(0),
|
bytes_per_second(0),
|
||||||
items_per_second(0),
|
items_per_second(0),
|
||||||
max_heapbytes_used(0),
|
max_heapbytes_used(0),
|
||||||
complexity(oNone),
|
complexity(oNone),
|
||||||
complexity_lambda(),
|
complexity_lambda(),
|
||||||
complexity_n(0),
|
complexity_n(0),
|
||||||
report_big_o(false),
|
report_big_o(false),
|
||||||
report_rms(false) {}
|
report_rms(false) {}
|
||||||
|
|
||||||
std::string benchmark_name;
|
std::string benchmark_name;
|
||||||
std::string report_label; // Empty if not set by benchmark.
|
std::string report_label; // Empty if not set by benchmark.
|
||||||
|
@ -134,13 +134,9 @@ class BenchmarkReporter {
|
||||||
error_stream_ = err;
|
error_stream_ = err;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& GetOutputStream() const {
|
std::ostream& GetOutputStream() const { return *output_stream_; }
|
||||||
return *output_stream_;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ostream& GetErrorStream() const {
|
std::ostream& GetErrorStream() const { return *error_stream_; }
|
||||||
return *error_stream_;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~BenchmarkReporter();
|
virtual ~BenchmarkReporter();
|
||||||
|
|
||||||
|
@ -157,22 +153,19 @@ class BenchmarkReporter {
|
||||||
// Simple reporter that outputs benchmark data to the console. This is the
|
// Simple reporter that outputs benchmark data to the console. This is the
|
||||||
// default reporter used by RunSpecifiedBenchmarks().
|
// default reporter used by RunSpecifiedBenchmarks().
|
||||||
class ConsoleReporter : public BenchmarkReporter {
|
class ConsoleReporter : public BenchmarkReporter {
|
||||||
public:
|
public:
|
||||||
enum OutputOptions {
|
enum OutputOptions { OO_None, OO_Color };
|
||||||
OO_None,
|
|
||||||
OO_Color
|
|
||||||
};
|
|
||||||
explicit ConsoleReporter(OutputOptions color_output = OO_Color)
|
explicit ConsoleReporter(OutputOptions color_output = OO_Color)
|
||||||
: name_field_width_(0), color_output_(color_output == OO_Color) {}
|
: name_field_width_(0), color_output_(color_output == OO_Color) {}
|
||||||
|
|
||||||
virtual bool ReportContext(const Context& context);
|
virtual bool ReportContext(const Context& context);
|
||||||
virtual void ReportRuns(const std::vector<Run>& reports);
|
virtual void ReportRuns(const std::vector<Run>& reports);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void PrintRunData(const Run& report);
|
virtual void PrintRunData(const Run& report);
|
||||||
size_t name_field_width_;
|
size_t name_field_width_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool color_output_;
|
bool color_output_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,6 @@ namespace internal {
|
||||||
// a pointer by mistake, you will get a compile-time error.
|
// a pointer by mistake, you will get a compile-time error.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
// This template function declaration is used in defining arraysize.
|
// This template function declaration is used in defining arraysize.
|
||||||
// Note that the function doesn't need an implementation, as we only
|
// Note that the function doesn't need an implementation, as we only
|
||||||
// use its type.
|
// use its type.
|
||||||
|
@ -28,7 +27,7 @@ char (&ArraySizeHelper(const T (&array)[N]))[N];
|
||||||
|
|
||||||
#define arraysize(array) (sizeof(::benchmark::internal::ArraySizeHelper(array)))
|
#define arraysize(array) (sizeof(::benchmark::internal::ArraySizeHelper(array)))
|
||||||
|
|
||||||
} // end namespace internal
|
} // end namespace internal
|
||||||
} // end namespace benchmark
|
} // end namespace benchmark
|
||||||
|
|
||||||
#endif // BENCHMARK_ARRAYSIZE_H_
|
#endif // BENCHMARK_ARRAYSIZE_H_
|
||||||
|
|
144
src/benchmark.cc
144
src/benchmark.cc
|
@ -13,23 +13,23 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#include "benchmark/benchmark.h"
|
#include "benchmark/benchmark.h"
|
||||||
#include "internal_macros.h"
|
|
||||||
#include "benchmark_api_internal.h"
|
#include "benchmark_api_internal.h"
|
||||||
|
#include "internal_macros.h"
|
||||||
|
|
||||||
#ifndef BENCHMARK_OS_WINDOWS
|
#ifndef BENCHMARK_OS_WINDOWS
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
|
#include <sys/time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cstring>
|
|
||||||
#include <cstdio>
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <iostream>
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
|
@ -92,7 +92,6 @@ DEFINE_string(benchmark_color, "auto",
|
||||||
|
|
||||||
DEFINE_int32(v, 0, "The level of verbose logging to output");
|
DEFINE_int32(v, 0, "The level of verbose logging to output");
|
||||||
|
|
||||||
|
|
||||||
namespace benchmark {
|
namespace benchmark {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
|
@ -108,7 +107,6 @@ static const size_t kMaxIterations = 1000000000;
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
|
|
||||||
class ThreadManager {
|
class ThreadManager {
|
||||||
public:
|
public:
|
||||||
ThreadManager(int num_threads)
|
ThreadManager(int num_threads)
|
||||||
|
@ -202,25 +200,23 @@ class ThreadTimer {
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool running_ = false; // Is the timer running
|
bool running_ = false; // Is the timer running
|
||||||
double start_real_time_ = 0; // If running_
|
double start_real_time_ = 0; // If running_
|
||||||
double start_cpu_time_ = 0; // If running_
|
double start_cpu_time_ = 0; // If running_
|
||||||
|
|
||||||
// Accumulated time so far (does not contain current slice if running_)
|
// Accumulated time so far (does not contain current slice if running_)
|
||||||
double real_time_used_ = 0;
|
double real_time_used_ = 0;
|
||||||
double cpu_time_used_ = 0;
|
double cpu_time_used_ = 0;
|
||||||
// Manually set iteration time. User sets this with SetIterationTime(seconds).
|
// Manually set iteration time. User sets this with SetIterationTime(seconds).
|
||||||
double manual_time_used_ = 0;
|
double manual_time_used_ = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
BenchmarkReporter::Run
|
BenchmarkReporter::Run CreateRunReport(
|
||||||
CreateRunReport(const benchmark::internal::Benchmark::Instance& b,
|
const benchmark::internal::Benchmark::Instance& b,
|
||||||
const internal::ThreadManager::Result& results,
|
const internal::ThreadManager::Result& results, size_t iters,
|
||||||
size_t iters, double seconds)
|
double seconds) {
|
||||||
{
|
|
||||||
// Create report about this benchmark run.
|
// Create report about this benchmark run.
|
||||||
BenchmarkReporter::Run report;
|
BenchmarkReporter::Run report;
|
||||||
|
|
||||||
|
@ -265,8 +261,8 @@ void RunInThread(const benchmark::internal::Benchmark::Instance* b,
|
||||||
internal::ThreadTimer timer;
|
internal::ThreadTimer timer;
|
||||||
State st(iters, b->arg, thread_id, b->threads, &timer, manager);
|
State st(iters, b->arg, thread_id, b->threads, &timer, manager);
|
||||||
b->benchmark->Run(st);
|
b->benchmark->Run(st);
|
||||||
CHECK(st.iterations() == st.max_iterations) <<
|
CHECK(st.iterations() == st.max_iterations)
|
||||||
"Benchmark returned before State::KeepRunning() returned false!";
|
<< "Benchmark returned before State::KeepRunning() returned false!";
|
||||||
{
|
{
|
||||||
MutexLock l(manager->GetBenchmarkMutex());
|
MutexLock l(manager->GetBenchmarkMutex());
|
||||||
internal::ThreadManager::Result& results = manager->results;
|
internal::ThreadManager::Result& results = manager->results;
|
||||||
|
@ -283,17 +279,18 @@ void RunInThread(const benchmark::internal::Benchmark::Instance* b,
|
||||||
std::vector<BenchmarkReporter::Run> RunBenchmark(
|
std::vector<BenchmarkReporter::Run> RunBenchmark(
|
||||||
const benchmark::internal::Benchmark::Instance& b,
|
const benchmark::internal::Benchmark::Instance& b,
|
||||||
std::vector<BenchmarkReporter::Run>* complexity_reports) {
|
std::vector<BenchmarkReporter::Run>* complexity_reports) {
|
||||||
std::vector<BenchmarkReporter::Run> reports; // return value
|
std::vector<BenchmarkReporter::Run> reports; // return value
|
||||||
|
|
||||||
size_t iters = 1;
|
size_t iters = 1;
|
||||||
std::unique_ptr<internal::ThreadManager> manager;
|
std::unique_ptr<internal::ThreadManager> manager;
|
||||||
std::vector<std::thread> pool(b.threads - 1);
|
std::vector<std::thread> pool(b.threads - 1);
|
||||||
const int repeats = b.repetitions != 0 ? b.repetitions
|
const int repeats =
|
||||||
: FLAGS_benchmark_repetitions;
|
b.repetitions != 0 ? b.repetitions : FLAGS_benchmark_repetitions;
|
||||||
const bool report_aggregates_only = repeats != 1 &&
|
const bool report_aggregates_only =
|
||||||
|
repeats != 1 &&
|
||||||
(b.report_mode == internal::RM_Unspecified
|
(b.report_mode == internal::RM_Unspecified
|
||||||
? FLAGS_benchmark_report_aggregates_only
|
? FLAGS_benchmark_report_aggregates_only
|
||||||
: b.report_mode == internal::RM_ReportAggregatesOnly);
|
: b.report_mode == internal::RM_ReportAggregatesOnly);
|
||||||
for (int i = 0; i < repeats; i++) {
|
for (int i = 0; i < repeats; i++) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
// Try benchmark
|
// Try benchmark
|
||||||
|
@ -306,8 +303,7 @@ std::vector<BenchmarkReporter::Run> RunBenchmark(
|
||||||
}
|
}
|
||||||
RunInThread(&b, iters, 0, manager.get());
|
RunInThread(&b, iters, 0, manager.get());
|
||||||
manager->WaitForAllThreads();
|
manager->WaitForAllThreads();
|
||||||
for (std::thread& thread : pool)
|
for (std::thread& thread : pool) thread.join();
|
||||||
thread.join();
|
|
||||||
internal::ThreadManager::Result results;
|
internal::ThreadManager::Result results;
|
||||||
{
|
{
|
||||||
MutexLock l(manager->GetBenchmarkMutex());
|
MutexLock l(manager->GetBenchmarkMutex());
|
||||||
|
@ -319,23 +315,24 @@ std::vector<BenchmarkReporter::Run> RunBenchmark(
|
||||||
results.manual_time_used /= b.threads;
|
results.manual_time_used /= b.threads;
|
||||||
|
|
||||||
VLOG(2) << "Ran in " << results.cpu_time_used << "/"
|
VLOG(2) << "Ran in " << results.cpu_time_used << "/"
|
||||||
<< results.real_time_used << "\n";
|
<< results.real_time_used << "\n";
|
||||||
|
|
||||||
// Base decisions off of real time if requested by this benchmark.
|
// Base decisions off of real time if requested by this benchmark.
|
||||||
double seconds = results.cpu_time_used;
|
double seconds = results.cpu_time_used;
|
||||||
if (b.use_manual_time) {
|
if (b.use_manual_time) {
|
||||||
seconds = results.manual_time_used;
|
seconds = results.manual_time_used;
|
||||||
} else if (b.use_real_time) {
|
} else if (b.use_real_time) {
|
||||||
seconds = results.real_time_used;
|
seconds = results.real_time_used;
|
||||||
}
|
}
|
||||||
|
|
||||||
const double min_time = !IsZero(b.min_time) ? b.min_time
|
const double min_time =
|
||||||
: FLAGS_benchmark_min_time;
|
!IsZero(b.min_time) ? b.min_time : FLAGS_benchmark_min_time;
|
||||||
// If this was the first run, was elapsed time or cpu time large enough?
|
// If this was the first run, was elapsed time or cpu time large enough?
|
||||||
// If this is not the first run, go with the current value of iter.
|
// If this is not the first run, go with the current value of iter.
|
||||||
if ((i > 0) || results.has_error_ || (iters >= kMaxIterations) ||
|
if ((i > 0) || results.has_error_ || (iters >= kMaxIterations) ||
|
||||||
(seconds >= min_time) || (results.real_time_used >= 5 * min_time)) {
|
(seconds >= min_time) || (results.real_time_used >= 5 * min_time)) {
|
||||||
BenchmarkReporter::Run report = CreateRunReport(b, results, iters, seconds);
|
BenchmarkReporter::Run report =
|
||||||
|
CreateRunReport(b, results, iters, seconds);
|
||||||
if (!report.error_occurred && b.complexity != oNone)
|
if (!report.error_occurred && b.complexity != oNone)
|
||||||
complexity_reports->push_back(report);
|
complexity_reports->push_back(report);
|
||||||
reports.push_back(report);
|
reports.push_back(report);
|
||||||
|
@ -363,10 +360,10 @@ std::vector<BenchmarkReporter::Run> RunBenchmark(
|
||||||
}
|
}
|
||||||
// Calculate additional statistics
|
// Calculate additional statistics
|
||||||
auto stat_reports = ComputeStats(reports);
|
auto stat_reports = ComputeStats(reports);
|
||||||
if((b.complexity != oNone) && b.last_benchmark_instance) {
|
if ((b.complexity != oNone) && b.last_benchmark_instance) {
|
||||||
auto additional_run_stats = ComputeBigO(*complexity_reports);
|
auto additional_run_stats = ComputeBigO(*complexity_reports);
|
||||||
stat_reports.insert(stat_reports.end(), additional_run_stats.begin(),
|
stat_reports.insert(stat_reports.end(), additional_run_stats.begin(),
|
||||||
additional_run_stats.end());
|
additional_run_stats.end());
|
||||||
complexity_reports->clear();
|
complexity_reports->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -375,8 +372,8 @@ std::vector<BenchmarkReporter::Run> RunBenchmark(
|
||||||
return reports;
|
return reports;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
State::State(size_t max_iters, const std::vector<int>& ranges, int thread_i,
|
State::State(size_t max_iters, const std::vector<int>& ranges, int thread_i,
|
||||||
int n_threads, internal::ThreadTimer* timer,
|
int n_threads, internal::ThreadTimer* timer,
|
||||||
|
@ -423,8 +420,7 @@ void State::SkipWithError(const char* msg) {
|
||||||
if (timer_->running()) timer_->StopTimer();
|
if (timer_->running()) timer_->StopTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void State::SetIterationTime(double seconds)
|
void State::SetIterationTime(double seconds) {
|
||||||
{
|
|
||||||
timer_->SetIterationTime(seconds);
|
timer_->SetIterationTime(seconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -468,8 +464,7 @@ void RunMatchingBenchmarks(const std::vector<Benchmark::Instance>& benchmarks,
|
||||||
std::max<size_t>(name_field_width, benchmark.name.size());
|
std::max<size_t>(name_field_width, benchmark.name.size());
|
||||||
has_repetitions |= benchmark.repetitions > 1;
|
has_repetitions |= benchmark.repetitions > 1;
|
||||||
}
|
}
|
||||||
if (has_repetitions)
|
if (has_repetitions) name_field_width += std::strlen("_stddev");
|
||||||
name_field_width += std::strlen("_stddev");
|
|
||||||
|
|
||||||
// Print header here
|
// Print header here
|
||||||
BenchmarkReporter::Context context;
|
BenchmarkReporter::Context context;
|
||||||
|
@ -490,8 +485,8 @@ void RunMatchingBenchmarks(const std::vector<Benchmark::Instance>& benchmarks,
|
||||||
std::flush(reporter->GetErrorStream());
|
std::flush(reporter->GetErrorStream());
|
||||||
};
|
};
|
||||||
|
|
||||||
if (console_reporter->ReportContext(context)
|
if (console_reporter->ReportContext(context) &&
|
||||||
&& (!file_reporter || file_reporter->ReportContext(context))) {
|
(!file_reporter || file_reporter->ReportContext(context))) {
|
||||||
flushStreams(console_reporter);
|
flushStreams(console_reporter);
|
||||||
flushStreams(file_reporter);
|
flushStreams(file_reporter);
|
||||||
for (const auto& benchmark : benchmarks) {
|
for (const auto& benchmark : benchmarks) {
|
||||||
|
@ -509,8 +504,8 @@ void RunMatchingBenchmarks(const std::vector<Benchmark::Instance>& benchmarks,
|
||||||
flushStreams(file_reporter);
|
flushStreams(file_reporter);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<BenchmarkReporter>
|
std::unique_ptr<BenchmarkReporter> CreateReporter(
|
||||||
CreateReporter(std::string const& name, ConsoleReporter::OutputOptions allow_color) {
|
std::string const& name, ConsoleReporter::OutputOptions allow_color) {
|
||||||
typedef std::unique_ptr<BenchmarkReporter> PtrType;
|
typedef std::unique_ptr<BenchmarkReporter> PtrType;
|
||||||
if (name == "console") {
|
if (name == "console") {
|
||||||
return PtrType(new ConsoleReporter(allow_color));
|
return PtrType(new ConsoleReporter(allow_color));
|
||||||
|
@ -524,19 +519,17 @@ CreateReporter(std::string const& name, ConsoleReporter::OutputOptions allow_col
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end namespace
|
} // end namespace
|
||||||
} // end namespace internal
|
} // end namespace internal
|
||||||
|
|
||||||
size_t RunSpecifiedBenchmarks() {
|
size_t RunSpecifiedBenchmarks() {
|
||||||
return RunSpecifiedBenchmarks(nullptr, nullptr);
|
return RunSpecifiedBenchmarks(nullptr, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
size_t RunSpecifiedBenchmarks(BenchmarkReporter* console_reporter) {
|
size_t RunSpecifiedBenchmarks(BenchmarkReporter* console_reporter) {
|
||||||
return RunSpecifiedBenchmarks(console_reporter, nullptr);
|
return RunSpecifiedBenchmarks(console_reporter, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
size_t RunSpecifiedBenchmarks(BenchmarkReporter* console_reporter,
|
size_t RunSpecifiedBenchmarks(BenchmarkReporter* console_reporter,
|
||||||
BenchmarkReporter* file_reporter) {
|
BenchmarkReporter* file_reporter) {
|
||||||
std::string spec = FLAGS_benchmark_filter;
|
std::string spec = FLAGS_benchmark_filter;
|
||||||
|
@ -556,8 +549,8 @@ size_t RunSpecifiedBenchmarks(BenchmarkReporter* console_reporter,
|
||||||
output_opts = IsTruthyFlagValue(FLAGS_benchmark_color)
|
output_opts = IsTruthyFlagValue(FLAGS_benchmark_color)
|
||||||
? ConsoleReporter::OO_Color
|
? ConsoleReporter::OO_Color
|
||||||
: ConsoleReporter::OO_None;
|
: ConsoleReporter::OO_None;
|
||||||
default_console_reporter = internal::CreateReporter(
|
default_console_reporter =
|
||||||
FLAGS_benchmark_format, output_opts);
|
internal::CreateReporter(FLAGS_benchmark_format, output_opts);
|
||||||
console_reporter = default_console_reporter.get();
|
console_reporter = default_console_reporter.get();
|
||||||
}
|
}
|
||||||
auto& Out = console_reporter->GetOutputStream();
|
auto& Out = console_reporter->GetOutputStream();
|
||||||
|
@ -566,7 +559,8 @@ size_t RunSpecifiedBenchmarks(BenchmarkReporter* console_reporter,
|
||||||
std::string const& fname = FLAGS_benchmark_out;
|
std::string const& fname = FLAGS_benchmark_out;
|
||||||
if (fname == "" && file_reporter) {
|
if (fname == "" && file_reporter) {
|
||||||
Err << "A custom file reporter was provided but "
|
Err << "A custom file reporter was provided but "
|
||||||
"--benchmark_out=<file> was not specified." << std::endl;
|
"--benchmark_out=<file> was not specified."
|
||||||
|
<< std::endl;
|
||||||
std::exit(1);
|
std::exit(1);
|
||||||
}
|
}
|
||||||
if (fname != "") {
|
if (fname != "") {
|
||||||
|
@ -577,7 +571,7 @@ size_t RunSpecifiedBenchmarks(BenchmarkReporter* console_reporter,
|
||||||
}
|
}
|
||||||
if (!file_reporter) {
|
if (!file_reporter) {
|
||||||
default_file_reporter = internal::CreateReporter(
|
default_file_reporter = internal::CreateReporter(
|
||||||
FLAGS_benchmark_out_format, ConsoleReporter::OO_None);
|
FLAGS_benchmark_out_format, ConsoleReporter::OO_None);
|
||||||
file_reporter = default_file_reporter.get();
|
file_reporter = default_file_reporter.get();
|
||||||
}
|
}
|
||||||
file_reporter->SetOutputStream(&output_file);
|
file_reporter->SetOutputStream(&output_file);
|
||||||
|
@ -588,10 +582,10 @@ size_t RunSpecifiedBenchmarks(BenchmarkReporter* console_reporter,
|
||||||
if (!FindBenchmarksInternal(spec, &benchmarks, &Err)) return 0;
|
if (!FindBenchmarksInternal(spec, &benchmarks, &Err)) return 0;
|
||||||
|
|
||||||
if (FLAGS_benchmark_list_tests) {
|
if (FLAGS_benchmark_list_tests) {
|
||||||
for (auto const& benchmark : benchmarks)
|
for (auto const& benchmark : benchmarks) Out << benchmark.name << "\n";
|
||||||
Out << benchmark.name << "\n";
|
|
||||||
} else {
|
} else {
|
||||||
internal::RunMatchingBenchmarks(benchmarks, console_reporter, file_reporter);
|
internal::RunMatchingBenchmarks(benchmarks, console_reporter,
|
||||||
|
file_reporter);
|
||||||
}
|
}
|
||||||
|
|
||||||
return benchmarks.size();
|
return benchmarks.size();
|
||||||
|
@ -618,29 +612,23 @@ void PrintUsageAndExit() {
|
||||||
void ParseCommandLineFlags(int* argc, char** argv) {
|
void ParseCommandLineFlags(int* argc, char** argv) {
|
||||||
using namespace benchmark;
|
using namespace benchmark;
|
||||||
for (int i = 1; i < *argc; ++i) {
|
for (int i = 1; i < *argc; ++i) {
|
||||||
if (
|
if (ParseBoolFlag(argv[i], "benchmark_list_tests",
|
||||||
ParseBoolFlag(argv[i], "benchmark_list_tests",
|
|
||||||
&FLAGS_benchmark_list_tests) ||
|
&FLAGS_benchmark_list_tests) ||
|
||||||
ParseStringFlag(argv[i], "benchmark_filter",
|
ParseStringFlag(argv[i], "benchmark_filter", &FLAGS_benchmark_filter) ||
|
||||||
&FLAGS_benchmark_filter) ||
|
|
||||||
ParseDoubleFlag(argv[i], "benchmark_min_time",
|
ParseDoubleFlag(argv[i], "benchmark_min_time",
|
||||||
&FLAGS_benchmark_min_time) ||
|
&FLAGS_benchmark_min_time) ||
|
||||||
ParseInt32Flag(argv[i], "benchmark_repetitions",
|
ParseInt32Flag(argv[i], "benchmark_repetitions",
|
||||||
&FLAGS_benchmark_repetitions) ||
|
&FLAGS_benchmark_repetitions) ||
|
||||||
ParseBoolFlag(argv[i], "benchmark_report_aggregates_only",
|
ParseBoolFlag(argv[i], "benchmark_report_aggregates_only",
|
||||||
&FLAGS_benchmark_report_aggregates_only) ||
|
&FLAGS_benchmark_report_aggregates_only) ||
|
||||||
ParseStringFlag(argv[i], "benchmark_format",
|
ParseStringFlag(argv[i], "benchmark_format", &FLAGS_benchmark_format) ||
|
||||||
&FLAGS_benchmark_format) ||
|
ParseStringFlag(argv[i], "benchmark_out", &FLAGS_benchmark_out) ||
|
||||||
ParseStringFlag(argv[i], "benchmark_out",
|
|
||||||
&FLAGS_benchmark_out) ||
|
|
||||||
ParseStringFlag(argv[i], "benchmark_out_format",
|
ParseStringFlag(argv[i], "benchmark_out_format",
|
||||||
&FLAGS_benchmark_out_format) ||
|
&FLAGS_benchmark_out_format) ||
|
||||||
ParseStringFlag(argv[i], "benchmark_color",
|
ParseStringFlag(argv[i], "benchmark_color", &FLAGS_benchmark_color) ||
|
||||||
&FLAGS_benchmark_color) ||
|
|
||||||
// "color_print" is the deprecated name for "benchmark_color".
|
// "color_print" is the deprecated name for "benchmark_color".
|
||||||
// TODO: Remove this.
|
// TODO: Remove this.
|
||||||
ParseStringFlag(argv[i], "color_print",
|
ParseStringFlag(argv[i], "color_print", &FLAGS_benchmark_color) ||
|
||||||
&FLAGS_benchmark_color) ||
|
|
||||||
ParseInt32Flag(argv[i], "v", &FLAGS_v)) {
|
ParseInt32Flag(argv[i], "v", &FLAGS_v)) {
|
||||||
for (int j = i; j != *argc; ++j) argv[j] = argv[j + 1];
|
for (int j = i; j != *argc; ++j) argv[j] = argv[j + 1];
|
||||||
|
|
||||||
|
@ -650,26 +638,26 @@ void ParseCommandLineFlags(int* argc, char** argv) {
|
||||||
PrintUsageAndExit();
|
PrintUsageAndExit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (auto const* flag : {&FLAGS_benchmark_format,
|
for (auto const* flag :
|
||||||
&FLAGS_benchmark_out_format})
|
{&FLAGS_benchmark_format, &FLAGS_benchmark_out_format})
|
||||||
if (*flag != "console" && *flag != "json" && *flag != "csv") {
|
if (*flag != "console" && *flag != "json" && *flag != "csv") {
|
||||||
PrintUsageAndExit();
|
PrintUsageAndExit();
|
||||||
}
|
}
|
||||||
if (FLAGS_benchmark_color.empty()) {
|
if (FLAGS_benchmark_color.empty()) {
|
||||||
PrintUsageAndExit();
|
PrintUsageAndExit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int InitializeStreams() {
|
int InitializeStreams() {
|
||||||
static std::ios_base::Init init;
|
static std::ios_base::Init init;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end namespace internal
|
} // end namespace internal
|
||||||
|
|
||||||
void Initialize(int* argc, char** argv) {
|
void Initialize(int* argc, char** argv) {
|
||||||
internal::ParseCommandLineFlags(argc, argv);
|
internal::ParseCommandLineFlags(argc, argv);
|
||||||
internal::LogLevel() = FLAGS_v;
|
internal::LogLevel() = FLAGS_v;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end namespace benchmark
|
} // end namespace benchmark
|
||||||
|
|
|
@ -3,44 +3,45 @@
|
||||||
|
|
||||||
#include "benchmark/benchmark_api.h"
|
#include "benchmark/benchmark_api.h"
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <limits>
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
|
#include <limits>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace benchmark {
|
namespace benchmark {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
// Information kept per benchmark we may want to run
|
// Information kept per benchmark we may want to run
|
||||||
struct Benchmark::Instance {
|
struct Benchmark::Instance {
|
||||||
std::string name;
|
std::string name;
|
||||||
Benchmark* benchmark;
|
Benchmark* benchmark;
|
||||||
ReportMode report_mode;
|
ReportMode report_mode;
|
||||||
std::vector<int> arg;
|
std::vector<int> arg;
|
||||||
TimeUnit time_unit;
|
TimeUnit time_unit;
|
||||||
int range_multiplier;
|
int range_multiplier;
|
||||||
bool use_real_time;
|
bool use_real_time;
|
||||||
bool use_manual_time;
|
bool use_manual_time;
|
||||||
BigO complexity;
|
BigO complexity;
|
||||||
BigOFunc* complexity_lambda;
|
BigOFunc* complexity_lambda;
|
||||||
bool last_benchmark_instance;
|
bool last_benchmark_instance;
|
||||||
int repetitions;
|
int repetitions;
|
||||||
double min_time;
|
double min_time;
|
||||||
int threads; // Number of concurrent threads to us
|
int threads; // Number of concurrent threads to us
|
||||||
};
|
};
|
||||||
|
|
||||||
bool FindBenchmarksInternal(const std::string& re,
|
bool FindBenchmarksInternal(const std::string& re,
|
||||||
std::vector<Benchmark::Instance>* benchmarks, std::ostream* Err);
|
std::vector<Benchmark::Instance>* benchmarks,
|
||||||
|
std::ostream* Err);
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
bool IsZero(double n) {
|
bool IsZero(double n) {
|
||||||
return std::abs(n) < std::numeric_limits<double>::epsilon();
|
return std::abs(n) < std::numeric_limits<double>::epsilon();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end namespace
|
} // end namespace
|
||||||
} // end namespace internal
|
} // end namespace internal
|
||||||
} // end namespace benchmark
|
} // end namespace benchmark
|
||||||
|
|
||||||
#endif // BENCHMARK_API_INTERNAL_H
|
#endif // BENCHMARK_API_INTERNAL_H
|
||||||
|
|
|
@ -13,23 +13,23 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#include "benchmark/benchmark.h"
|
#include "benchmark/benchmark.h"
|
||||||
#include "internal_macros.h"
|
|
||||||
#include "benchmark_api_internal.h"
|
#include "benchmark_api_internal.h"
|
||||||
|
#include "internal_macros.h"
|
||||||
|
|
||||||
#ifndef BENCHMARK_OS_WINDOWS
|
#ifndef BENCHMARK_OS_WINDOWS
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
|
#include <sys/time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cstring>
|
|
||||||
#include <cstdio>
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <iostream>
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
|
@ -74,6 +74,7 @@ class BenchmarkFamilies {
|
||||||
bool FindBenchmarks(const std::string& re,
|
bool FindBenchmarks(const std::string& re,
|
||||||
std::vector<Benchmark::Instance>* benchmarks,
|
std::vector<Benchmark::Instance>* benchmarks,
|
||||||
std::ostream* Err);
|
std::ostream* Err);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BenchmarkFamilies() {}
|
BenchmarkFamilies() {}
|
||||||
|
|
||||||
|
@ -94,8 +95,7 @@ size_t BenchmarkFamilies::AddBenchmark(std::unique_ptr<Benchmark> family) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BenchmarkFamilies::FindBenchmarks(
|
bool BenchmarkFamilies::FindBenchmarks(
|
||||||
const std::string& spec,
|
const std::string& spec, std::vector<Benchmark::Instance>* benchmarks,
|
||||||
std::vector<Benchmark::Instance>* benchmarks,
|
|
||||||
std::ostream* ErrStream) {
|
std::ostream* ErrStream) {
|
||||||
CHECK(ErrStream);
|
CHECK(ErrStream);
|
||||||
auto& Err = *ErrStream;
|
auto& Err = *ErrStream;
|
||||||
|
@ -120,23 +120,21 @@ bool BenchmarkFamilies::FindBenchmarks(
|
||||||
}
|
}
|
||||||
const std::vector<int>* thread_counts =
|
const std::vector<int>* thread_counts =
|
||||||
(family->thread_counts_.empty()
|
(family->thread_counts_.empty()
|
||||||
? &one_thread
|
? &one_thread
|
||||||
: &static_cast<const std::vector<int>&>(family->thread_counts_));
|
: &static_cast<const std::vector<int>&>(family->thread_counts_));
|
||||||
const size_t family_size = family->args_.size() * thread_counts->size();
|
const size_t family_size = family->args_.size() * thread_counts->size();
|
||||||
// The benchmark will be run at least 'family_size' different inputs.
|
// The benchmark will be run at least 'family_size' different inputs.
|
||||||
// If 'family_size' is very large warn the user.
|
// If 'family_size' is very large warn the user.
|
||||||
if (family_size > kMaxFamilySize) {
|
if (family_size > kMaxFamilySize) {
|
||||||
Err << "The number of inputs is very large. " << family->name_
|
Err << "The number of inputs is very large. " << family->name_
|
||||||
<< " will be repeated at least " << family_size << " times.\n";
|
<< " will be repeated at least " << family_size << " times.\n";
|
||||||
}
|
}
|
||||||
// reserve in the special case the regex ".", since we know the final
|
// reserve in the special case the regex ".", since we know the final
|
||||||
// family size.
|
// family size.
|
||||||
if (spec == ".")
|
if (spec == ".") benchmarks->reserve(family_size);
|
||||||
benchmarks->reserve(family_size);
|
|
||||||
|
|
||||||
for (auto const& args : family->args_) {
|
for (auto const& args : family->args_) {
|
||||||
for (int num_threads : *thread_counts) {
|
for (int num_threads : *thread_counts) {
|
||||||
|
|
||||||
Benchmark::Instance instance;
|
Benchmark::Instance instance;
|
||||||
instance.name = family->name_;
|
instance.name = family->name_;
|
||||||
instance.benchmark = family.get();
|
instance.benchmark = family.get();
|
||||||
|
@ -158,15 +156,15 @@ bool BenchmarkFamilies::FindBenchmarks(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsZero(family->min_time_)) {
|
if (!IsZero(family->min_time_)) {
|
||||||
instance.name += StringPrintF("/min_time:%0.3f", family->min_time_);
|
instance.name += StringPrintF("/min_time:%0.3f", family->min_time_);
|
||||||
}
|
}
|
||||||
if (family->repetitions_ != 0) {
|
if (family->repetitions_ != 0) {
|
||||||
instance.name += StringPrintF("/repeats:%d", family->repetitions_);
|
instance.name += StringPrintF("/repeats:%d", family->repetitions_);
|
||||||
}
|
}
|
||||||
if (family->use_manual_time_) {
|
if (family->use_manual_time_) {
|
||||||
instance.name += "/manual_time";
|
instance.name += "/manual_time";
|
||||||
} else if (family->use_real_time_) {
|
} else if (family->use_real_time_) {
|
||||||
instance.name += "/real_time";
|
instance.name += "/real_time";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the number of threads used to the name
|
// Add the number of threads used to the name
|
||||||
|
@ -185,37 +183,37 @@ bool BenchmarkFamilies::FindBenchmarks(
|
||||||
}
|
}
|
||||||
|
|
||||||
Benchmark* RegisterBenchmarkInternal(Benchmark* bench) {
|
Benchmark* RegisterBenchmarkInternal(Benchmark* bench) {
|
||||||
std::unique_ptr<Benchmark> bench_ptr(bench);
|
std::unique_ptr<Benchmark> bench_ptr(bench);
|
||||||
BenchmarkFamilies* families = BenchmarkFamilies::GetInstance();
|
BenchmarkFamilies* families = BenchmarkFamilies::GetInstance();
|
||||||
families->AddBenchmark(std::move(bench_ptr));
|
families->AddBenchmark(std::move(bench_ptr));
|
||||||
return bench;
|
return bench;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// FIXME: This function is a hack so that benchmark.cc can access
|
// FIXME: This function is a hack so that benchmark.cc can access
|
||||||
// `BenchmarkFamilies`
|
// `BenchmarkFamilies`
|
||||||
bool FindBenchmarksInternal(const std::string& re,
|
bool FindBenchmarksInternal(const std::string& re,
|
||||||
std::vector<Benchmark::Instance>* benchmarks,
|
std::vector<Benchmark::Instance>* benchmarks,
|
||||||
std::ostream* Err)
|
std::ostream* Err) {
|
||||||
{
|
|
||||||
return BenchmarkFamilies::GetInstance()->FindBenchmarks(re, benchmarks, Err);
|
return BenchmarkFamilies::GetInstance()->FindBenchmarks(re, benchmarks, Err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================//
|
//=============================================================================//
|
||||||
// Benchmark
|
// Benchmark
|
||||||
//=============================================================================//
|
//=============================================================================//
|
||||||
|
|
||||||
Benchmark::Benchmark(const char* name)
|
Benchmark::Benchmark(const char* name)
|
||||||
: name_(name), report_mode_(RM_Unspecified),
|
: name_(name),
|
||||||
time_unit_(kNanosecond), range_multiplier_(kRangeMultiplier),
|
report_mode_(RM_Unspecified),
|
||||||
min_time_(0), repetitions_(0), use_real_time_(false),
|
time_unit_(kNanosecond),
|
||||||
use_manual_time_(false), complexity_(oNone), complexity_lambda_(nullptr)
|
range_multiplier_(kRangeMultiplier),
|
||||||
{
|
min_time_(0),
|
||||||
}
|
repetitions_(0),
|
||||||
|
use_real_time_(false),
|
||||||
|
use_manual_time_(false),
|
||||||
|
complexity_(oNone),
|
||||||
|
complexity_lambda_(nullptr) {}
|
||||||
|
|
||||||
Benchmark::~Benchmark() {
|
Benchmark::~Benchmark() {}
|
||||||
}
|
|
||||||
|
|
||||||
void Benchmark::AddRange(std::vector<int>* dst, int lo, int hi, int mult) {
|
void Benchmark::AddRange(std::vector<int>* dst, int lo, int hi, int mult) {
|
||||||
CHECK_GE(lo, 0);
|
CHECK_GE(lo, 0);
|
||||||
|
@ -228,7 +226,7 @@ void Benchmark::AddRange(std::vector<int>* dst, int lo, int hi, int mult) {
|
||||||
static const int kint32max = std::numeric_limits<int32_t>::max();
|
static const int kint32max = std::numeric_limits<int32_t>::max();
|
||||||
|
|
||||||
// Now space out the benchmarks in multiples of "mult"
|
// Now space out the benchmarks in multiples of "mult"
|
||||||
for (int32_t i = 1; i < kint32max/mult; i *= mult) {
|
for (int32_t i = 1; i < kint32max / mult; i *= mult) {
|
||||||
if (i >= hi) break;
|
if (i >= hi) break;
|
||||||
if (i > lo) {
|
if (i > lo) {
|
||||||
dst->push_back(i);
|
dst->push_back(i);
|
||||||
|
@ -262,13 +260,13 @@ Benchmark* Benchmark::Range(int start, int limit) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Benchmark* Benchmark::Ranges(const std::vector<std::pair<int, int>>& ranges)
|
Benchmark* Benchmark::Ranges(const std::vector<std::pair<int, int>>& ranges) {
|
||||||
{
|
|
||||||
CHECK(ArgsCnt() == -1 || ArgsCnt() == static_cast<int>(ranges.size()));
|
CHECK(ArgsCnt() == -1 || ArgsCnt() == static_cast<int>(ranges.size()));
|
||||||
std::vector<std::vector<int>> arglists(ranges.size());
|
std::vector<std::vector<int>> arglists(ranges.size());
|
||||||
std::size_t total = 1;
|
std::size_t total = 1;
|
||||||
for (std::size_t i = 0; i < ranges.size(); i++) {
|
for (std::size_t i = 0; i < ranges.size(); i++) {
|
||||||
AddRange(&arglists[i], ranges[i].first, ranges[i].second, range_multiplier_);
|
AddRange(&arglists[i], ranges[i].first, ranges[i].second,
|
||||||
|
range_multiplier_);
|
||||||
total *= arglists[i].size();
|
total *= arglists[i].size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,7 +297,7 @@ Benchmark* Benchmark::DenseRange(int start, int limit, int step) {
|
||||||
CHECK(ArgsCnt() == -1 || ArgsCnt() == 1);
|
CHECK(ArgsCnt() == -1 || ArgsCnt() == 1);
|
||||||
CHECK_GE(start, 0);
|
CHECK_GE(start, 0);
|
||||||
CHECK_LE(start, limit);
|
CHECK_LE(start, limit);
|
||||||
for (int arg = start; arg <= limit; arg+= step) {
|
for (int arg = start; arg <= limit; arg += step) {
|
||||||
args_.push_back({arg});
|
args_.push_back({arg});
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
|
@ -340,13 +338,15 @@ Benchmark* Benchmark::MinTime(double t) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Benchmark* Benchmark::UseRealTime() {
|
Benchmark* Benchmark::UseRealTime() {
|
||||||
CHECK(!use_manual_time_) << "Cannot set UseRealTime and UseManualTime simultaneously.";
|
CHECK(!use_manual_time_)
|
||||||
|
<< "Cannot set UseRealTime and UseManualTime simultaneously.";
|
||||||
use_real_time_ = true;
|
use_real_time_ = true;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Benchmark* Benchmark::UseManualTime() {
|
Benchmark* Benchmark::UseManualTime() {
|
||||||
CHECK(!use_real_time_) << "Cannot set UseRealTime and UseManualTime simultaneously.";
|
CHECK(!use_real_time_)
|
||||||
|
<< "Cannot set UseRealTime and UseManualTime simultaneously.";
|
||||||
use_manual_time_ = true;
|
use_manual_time_ = true;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -376,7 +376,7 @@ Benchmark* Benchmark::ThreadRange(int min_threads, int max_threads) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Benchmark *Benchmark::DenseThreadRange(int min_threads, int max_threads,
|
Benchmark* Benchmark::DenseThreadRange(int min_threads, int max_threads,
|
||||||
int stride) {
|
int stride) {
|
||||||
CHECK_GT(min_threads, 0);
|
CHECK_GT(min_threads, 0);
|
||||||
CHECK_GE(max_threads, min_threads);
|
CHECK_GE(max_threads, min_threads);
|
||||||
|
@ -395,21 +395,17 @@ Benchmark* Benchmark::ThreadPerCpu() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Benchmark::SetName(const char* name) {
|
void Benchmark::SetName(const char* name) { name_ = name; }
|
||||||
name_ = name;
|
|
||||||
|
int Benchmark::ArgsCnt() const {
|
||||||
|
return args_.empty() ? -1 : static_cast<int>(args_.front().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
int Benchmark::ArgsCnt() const
|
|
||||||
{ return args_.empty() ? -1 : static_cast<int>(args_.front().size()); }
|
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================//
|
//=============================================================================//
|
||||||
// FunctionBenchmark
|
// FunctionBenchmark
|
||||||
//=============================================================================//
|
//=============================================================================//
|
||||||
|
|
||||||
void FunctionBenchmark::Run(State& st) {
|
void FunctionBenchmark::Run(State& st) { func_(st); }
|
||||||
func_(st);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end namespace internal
|
} // end namespace internal
|
||||||
} // end namespace benchmark
|
} // end namespace benchmark
|
||||||
|
|
41
src/check.h
41
src/check.h
|
@ -13,51 +13,52 @@ namespace internal {
|
||||||
typedef void(AbortHandlerT)();
|
typedef void(AbortHandlerT)();
|
||||||
|
|
||||||
inline AbortHandlerT*& GetAbortHandler() {
|
inline AbortHandlerT*& GetAbortHandler() {
|
||||||
static AbortHandlerT* handler = &std::abort;
|
static AbortHandlerT* handler = &std::abort;
|
||||||
return handler;
|
return handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCHMARK_NORETURN inline void CallAbortHandler() {
|
BENCHMARK_NORETURN inline void CallAbortHandler() {
|
||||||
GetAbortHandler()();
|
GetAbortHandler()();
|
||||||
std::abort(); // fallback to enforce noreturn
|
std::abort(); // fallback to enforce noreturn
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckHandler is the class constructed by failing CHECK macros. CheckHandler
|
// CheckHandler is the class constructed by failing CHECK macros. CheckHandler
|
||||||
// will log information about the failures and abort when it is destructed.
|
// will log information about the failures and abort when it is destructed.
|
||||||
class CheckHandler {
|
class CheckHandler {
|
||||||
public:
|
public:
|
||||||
CheckHandler(const char* check, const char* file, const char* func, int line)
|
CheckHandler(const char* check, const char* file, const char* func, int line)
|
||||||
: log_(GetErrorLogInstance())
|
: log_(GetErrorLogInstance()) {
|
||||||
{
|
log_ << file << ":" << line << ": " << func << ": Check `" << check
|
||||||
log_ << file << ":" << line << ": " << func << ": Check `"
|
<< "' failed. ";
|
||||||
<< check << "' failed. ";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LogType& GetLog() { return log_; }
|
LogType& GetLog() { return log_; }
|
||||||
|
|
||||||
BENCHMARK_NORETURN ~CheckHandler() BENCHMARK_NOEXCEPT_OP(false) {
|
BENCHMARK_NORETURN ~CheckHandler() BENCHMARK_NOEXCEPT_OP(false) {
|
||||||
log_ << std::endl;
|
log_ << std::endl;
|
||||||
CallAbortHandler();
|
CallAbortHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckHandler & operator=(const CheckHandler&) = delete;
|
CheckHandler& operator=(const CheckHandler&) = delete;
|
||||||
CheckHandler(const CheckHandler&) = delete;
|
CheckHandler(const CheckHandler&) = delete;
|
||||||
CheckHandler() = delete;
|
CheckHandler() = delete;
|
||||||
private:
|
|
||||||
LogType& log_;
|
private:
|
||||||
|
LogType& log_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace internal
|
} // end namespace internal
|
||||||
} // end namespace benchmark
|
} // end namespace benchmark
|
||||||
|
|
||||||
// The CHECK macro returns a std::ostream object that can have extra information
|
// The CHECK macro returns a std::ostream object that can have extra information
|
||||||
// written to it.
|
// written to it.
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
# define CHECK(b) (b ? ::benchmark::internal::GetNullLogInstance() \
|
#define CHECK(b) \
|
||||||
: ::benchmark::internal::CheckHandler( \
|
(b ? ::benchmark::internal::GetNullLogInstance() \
|
||||||
#b, __FILE__, __func__, __LINE__).GetLog())
|
: ::benchmark::internal::CheckHandler(#b, __FILE__, __func__, __LINE__) \
|
||||||
|
.GetLog())
|
||||||
#else
|
#else
|
||||||
# define CHECK(b) ::benchmark::internal::GetNullLogInstance()
|
#define CHECK(b) ::benchmark::internal::GetNullLogInstance()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define CHECK_EQ(a, b) CHECK((a) == (b))
|
#define CHECK_EQ(a, b) CHECK((a) == (b))
|
||||||
|
|
|
@ -25,11 +25,11 @@
|
||||||
#include "internal_macros.h"
|
#include "internal_macros.h"
|
||||||
|
|
||||||
#ifdef BENCHMARK_OS_WINDOWS
|
#ifdef BENCHMARK_OS_WINDOWS
|
||||||
#include <io.h>
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
#include <io.h>
|
||||||
#else
|
#else
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif // BENCHMARK_OS_WINDOWS
|
#endif // BENCHMARK_OS_WINDOWS
|
||||||
|
|
||||||
namespace benchmark {
|
namespace benchmark {
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -82,7 +82,7 @@ PlatformColorCode GetPlatformColorCode(LogColor color) {
|
||||||
|
|
||||||
} // end namespace
|
} // end namespace
|
||||||
|
|
||||||
std::string FormatString(const char *msg, va_list args) {
|
std::string FormatString(const char* msg, va_list args) {
|
||||||
// we might need a second shot at this, so pre-emptivly make a copy
|
// we might need a second shot at this, so pre-emptivly make a copy
|
||||||
va_list args_cp;
|
va_list args_cp;
|
||||||
va_copy(args_cp, args);
|
va_copy(args_cp, args);
|
||||||
|
@ -96,13 +96,13 @@ std::string FormatString(const char *msg, va_list args) {
|
||||||
// currently there is no error handling for failure, so this is hack.
|
// currently there is no error handling for failure, so this is hack.
|
||||||
CHECK(ret >= 0);
|
CHECK(ret >= 0);
|
||||||
|
|
||||||
if (ret == 0) // handle empty expansion
|
if (ret == 0) // handle empty expansion
|
||||||
return {};
|
return {};
|
||||||
else if (static_cast<size_t>(ret) < size)
|
else if (static_cast<size_t>(ret) < size)
|
||||||
return local_buff;
|
return local_buff;
|
||||||
else {
|
else {
|
||||||
// we did not provide a long enough buffer on our first attempt.
|
// we did not provide a long enough buffer on our first attempt.
|
||||||
size = (size_t)ret + 1; // + 1 for the null byte
|
size = (size_t)ret + 1; // + 1 for the null byte
|
||||||
std::unique_ptr<char[]> buff(new char[size]);
|
std::unique_ptr<char[]> buff(new char[size]);
|
||||||
ret = std::vsnprintf(buff.get(), size, msg, args);
|
ret = std::vsnprintf(buff.get(), size, msg, args);
|
||||||
CHECK(ret > 0 && ((size_t)ret) < size);
|
CHECK(ret > 0 && ((size_t)ret) < size);
|
||||||
|
@ -110,7 +110,7 @@ std::string FormatString(const char *msg, va_list args) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string FormatString(const char *msg, ...) {
|
std::string FormatString(const char* msg, ...) {
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, msg);
|
va_start(args, msg);
|
||||||
auto tmp = FormatString(msg, args);
|
auto tmp = FormatString(msg, args);
|
||||||
|
@ -125,9 +125,10 @@ void ColorPrintf(std::ostream& out, LogColor color, const char* fmt, ...) {
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ColorPrintf(std::ostream& out, LogColor color, const char* fmt, va_list args) {
|
void ColorPrintf(std::ostream& out, LogColor color, const char* fmt,
|
||||||
|
va_list args) {
|
||||||
#ifdef BENCHMARK_OS_WINDOWS
|
#ifdef BENCHMARK_OS_WINDOWS
|
||||||
((void)out); // suppress unused warning
|
((void)out); // suppress unused warning
|
||||||
|
|
||||||
const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
|
||||||
|
@ -152,7 +153,6 @@ void ColorPrintf(std::ostream& out, LogColor color, const char* fmt, va_list arg
|
||||||
if (color_code) out << FormatString("\033[0;3%sm", color_code);
|
if (color_code) out << FormatString("\033[0;3%sm", color_code);
|
||||||
out << FormatString(fmt, args) << "\033[m";
|
out << FormatString(fmt, args) << "\033[m";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsColorTerminal() {
|
bool IsColorTerminal() {
|
||||||
|
@ -182,7 +182,7 @@ bool IsColorTerminal() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0 != isatty(fileno(stdout)) && term_supports_color;
|
return 0 != isatty(fileno(stdout)) && term_supports_color;
|
||||||
#endif // BENCHMARK_OS_WINDOWS
|
#endif // BENCHMARK_OS_WINDOWS
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end namespace benchmark
|
} // end namespace benchmark
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
#define BENCHMARK_COLORPRINT_H_
|
#define BENCHMARK_COLORPRINT_H_
|
||||||
|
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
#include <string>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace benchmark {
|
namespace benchmark {
|
||||||
enum LogColor {
|
enum LogColor {
|
||||||
|
@ -20,7 +20,8 @@ enum LogColor {
|
||||||
std::string FormatString(const char* msg, va_list args);
|
std::string FormatString(const char* msg, va_list args);
|
||||||
std::string FormatString(const char* msg, ...);
|
std::string FormatString(const char* msg, ...);
|
||||||
|
|
||||||
void ColorPrintf(std::ostream& out, LogColor color, const char* fmt, va_list args);
|
void ColorPrintf(std::ostream& out, LogColor color, const char* fmt,
|
||||||
|
va_list args);
|
||||||
void ColorPrintf(std::ostream& out, LogColor color, const char* fmt, ...);
|
void ColorPrintf(std::ostream& out, LogColor color, const char* fmt, ...);
|
||||||
|
|
||||||
// Returns true if stdout appears to be a terminal that supports colored
|
// Returns true if stdout appears to be a terminal that supports colored
|
||||||
|
|
|
@ -44,7 +44,7 @@ bool ParseInt32(const std::string& src_text, const char* str, int32_t* value) {
|
||||||
// The parsed value overflows as a long. (strtol() returns
|
// The parsed value overflows as a long. (strtol() returns
|
||||||
// LONG_MAX or LONG_MIN when the input overflows.)
|
// LONG_MAX or LONG_MIN when the input overflows.)
|
||||||
result != long_value
|
result != long_value
|
||||||
// The parsed value overflows as an Int32.
|
// The parsed value overflows as an Int32.
|
||||||
) {
|
) {
|
||||||
std::cerr << src_text << " is expected to be a 32-bit integer, "
|
std::cerr << src_text << " is expected to be a 32-bit integer, "
|
||||||
<< "but actually has value \"" << str << "\", "
|
<< "but actually has value \"" << str << "\", "
|
||||||
|
@ -95,7 +95,8 @@ static std::string FlagToEnvVar(const char* flag) {
|
||||||
bool BoolFromEnv(const char* flag, bool default_value) {
|
bool BoolFromEnv(const char* flag, bool default_value) {
|
||||||
const std::string env_var = FlagToEnvVar(flag);
|
const std::string env_var = FlagToEnvVar(flag);
|
||||||
const char* const string_value = getenv(env_var.c_str());
|
const char* const string_value = getenv(env_var.c_str());
|
||||||
return string_value == nullptr ? default_value : strcmp(string_value, "0") != 0;
|
return string_value == nullptr ? default_value
|
||||||
|
: strcmp(string_value, "0") != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reads and returns a 32-bit integer stored in the environment
|
// Reads and returns a 32-bit integer stored in the environment
|
||||||
|
@ -209,8 +210,7 @@ bool IsFlag(const char* str, const char* flag) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsTruthyFlagValue(const std::string& str) {
|
bool IsTruthyFlagValue(const std::string& str) {
|
||||||
if (str.empty())
|
if (str.empty()) return true;
|
||||||
return true;
|
|
||||||
char ch = str[0];
|
char ch = str[0];
|
||||||
return isalnum(ch) &&
|
return isalnum(ch) &&
|
||||||
!(ch == '0' || ch == 'f' || ch == 'F' || ch == 'n' || ch == 'N');
|
!(ch == '0' || ch == 'f' || ch == 'F' || ch == 'n' || ch == 'N');
|
||||||
|
|
|
@ -119,8 +119,7 @@ LeastSq MinimalLeastSq(const std::vector<int>& n,
|
||||||
// this one. If it is oAuto, it will be calculated the best
|
// this one. If it is oAuto, it will be calculated the best
|
||||||
// fitting curve.
|
// fitting curve.
|
||||||
LeastSq MinimalLeastSq(const std::vector<int>& n,
|
LeastSq MinimalLeastSq(const std::vector<int>& n,
|
||||||
const std::vector<double>& time,
|
const std::vector<double>& time, const BigO complexity) {
|
||||||
const BigO complexity) {
|
|
||||||
CHECK_EQ(n.size(), time.size());
|
CHECK_EQ(n.size(), time.size());
|
||||||
CHECK_GE(n.size(), 2); // Do not compute fitting curve is less than two
|
CHECK_GE(n.size(), 2); // Do not compute fitting curve is less than two
|
||||||
// benchmark runs are given
|
// benchmark runs are given
|
||||||
|
|
|
@ -47,10 +47,7 @@ std::vector<BenchmarkReporter::Run> ComputeBigO(
|
||||||
// parameter will return the best fitting curve detected.
|
// parameter will return the best fitting curve detected.
|
||||||
|
|
||||||
struct LeastSq {
|
struct LeastSq {
|
||||||
LeastSq() :
|
LeastSq() : coef(0.0), rms(0.0), complexity(oNone) {}
|
||||||
coef(0.0),
|
|
||||||
rms(0.0),
|
|
||||||
complexity(oNone) {}
|
|
||||||
|
|
||||||
double coef;
|
double coef;
|
||||||
double rms;
|
double rms;
|
||||||
|
@ -60,5 +57,5 @@ struct LeastSq {
|
||||||
// Function to return an string for the calculated complexity
|
// Function to return an string for the calculated complexity
|
||||||
std::string GetBigOString(BigO complexity);
|
std::string GetBigOString(BigO complexity);
|
||||||
|
|
||||||
} // end namespace benchmark
|
} // end namespace benchmark
|
||||||
#endif // COMPLEXITY_H_
|
#endif // COMPLEXITY_H_
|
||||||
|
|
|
@ -39,46 +39,45 @@ bool ConsoleReporter::ReportContext(const Context& context) {
|
||||||
|
|
||||||
#ifdef BENCHMARK_OS_WINDOWS
|
#ifdef BENCHMARK_OS_WINDOWS
|
||||||
if (color_output_ && &std::cout != &GetOutputStream()) {
|
if (color_output_ && &std::cout != &GetOutputStream()) {
|
||||||
GetErrorStream() << "Color printing is only supported for stdout on windows."
|
GetErrorStream()
|
||||||
" Disabling color printing\n";
|
<< "Color printing is only supported for stdout on windows."
|
||||||
color_output_ = false;
|
" Disabling color printing\n";
|
||||||
|
color_output_ = false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
std::string str = FormatString("%-*s %13s %13s %10s\n",
|
std::string str =
|
||||||
static_cast<int>(name_field_width_), "Benchmark",
|
FormatString("%-*s %13s %13s %10s\n", static_cast<int>(name_field_width_),
|
||||||
"Time", "CPU", "Iterations");
|
"Benchmark", "Time", "CPU", "Iterations");
|
||||||
GetOutputStream() << str << std::string(str.length() - 1, '-') << "\n";
|
GetOutputStream() << str << std::string(str.length() - 1, '-') << "\n";
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleReporter::ReportRuns(const std::vector<Run>& reports) {
|
void ConsoleReporter::ReportRuns(const std::vector<Run>& reports) {
|
||||||
for (const auto& run : reports)
|
for (const auto& run : reports) PrintRunData(run);
|
||||||
PrintRunData(run);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void IgnoreColorPrint(std::ostream& out, LogColor,
|
static void IgnoreColorPrint(std::ostream& out, LogColor, const char* fmt,
|
||||||
const char* fmt, ...)
|
...) {
|
||||||
{
|
va_list args;
|
||||||
va_list args;
|
va_start(args, fmt);
|
||||||
va_start(args, fmt);
|
out << FormatString(fmt, args);
|
||||||
out << FormatString(fmt, args);
|
va_end(args);
|
||||||
va_end(args);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleReporter::PrintRunData(const Run& result) {
|
void ConsoleReporter::PrintRunData(const Run& result) {
|
||||||
typedef void(PrinterFn)(std::ostream&, LogColor, const char*, ...);
|
typedef void(PrinterFn)(std::ostream&, LogColor, const char*, ...);
|
||||||
auto& Out = GetOutputStream();
|
auto& Out = GetOutputStream();
|
||||||
PrinterFn* printer = color_output_ ? (PrinterFn*)ColorPrintf
|
PrinterFn* printer =
|
||||||
: IgnoreColorPrint;
|
color_output_ ? (PrinterFn*)ColorPrintf : IgnoreColorPrint;
|
||||||
auto name_color =
|
auto name_color =
|
||||||
(result.report_big_o || result.report_rms) ? COLOR_BLUE : COLOR_GREEN;
|
(result.report_big_o || result.report_rms) ? COLOR_BLUE : COLOR_GREEN;
|
||||||
printer(Out, name_color, "%-*s ", name_field_width_,
|
printer(Out, name_color, "%-*s ", name_field_width_,
|
||||||
result.benchmark_name.c_str());
|
result.benchmark_name.c_str());
|
||||||
|
|
||||||
if (result.error_occurred) {
|
if (result.error_occurred) {
|
||||||
printer(Out, COLOR_RED, "ERROR OCCURRED: \'%s\'",
|
printer(Out, COLOR_RED, "ERROR OCCURRED: \'%s\'",
|
||||||
result.error_message.c_str());
|
result.error_message.c_str());
|
||||||
printer(Out, COLOR_DEFAULT, "\n");
|
printer(Out, COLOR_DEFAULT, "\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -91,24 +90,24 @@ void ConsoleReporter::PrintRunData(const Run& result) {
|
||||||
// Format items per second
|
// Format items per second
|
||||||
std::string items;
|
std::string items;
|
||||||
if (result.items_per_second > 0) {
|
if (result.items_per_second > 0) {
|
||||||
items = StrCat(" ", HumanReadableNumber(result.items_per_second),
|
items =
|
||||||
" items/s");
|
StrCat(" ", HumanReadableNumber(result.items_per_second), " items/s");
|
||||||
}
|
}
|
||||||
|
|
||||||
const double real_time = result.GetAdjustedRealTime();
|
const double real_time = result.GetAdjustedRealTime();
|
||||||
const double cpu_time = result.GetAdjustedCPUTime();
|
const double cpu_time = result.GetAdjustedCPUTime();
|
||||||
|
|
||||||
if (result.report_big_o) {
|
if (result.report_big_o) {
|
||||||
std::string big_o = GetBigOString(result.complexity);
|
std::string big_o = GetBigOString(result.complexity);
|
||||||
printer(Out, COLOR_YELLOW, "%10.2f %s %10.2f %s ", real_time,
|
printer(Out, COLOR_YELLOW, "%10.2f %s %10.2f %s ", real_time, big_o.c_str(),
|
||||||
big_o.c_str(), cpu_time, big_o.c_str());
|
cpu_time, big_o.c_str());
|
||||||
} else if (result.report_rms) {
|
} else if (result.report_rms) {
|
||||||
printer(Out, COLOR_YELLOW, "%10.0f %% %10.0f %% ", real_time * 100,
|
printer(Out, COLOR_YELLOW, "%10.0f %% %10.0f %% ", real_time * 100,
|
||||||
cpu_time * 100);
|
cpu_time * 100);
|
||||||
} else {
|
} else {
|
||||||
const char* timeLabel = GetTimeUnitString(result.time_unit);
|
const char* timeLabel = GetTimeUnitString(result.time_unit);
|
||||||
printer(Out, COLOR_YELLOW, "%10.0f %s %10.0f %s ", real_time, timeLabel,
|
printer(Out, COLOR_YELLOW, "%10.0f %s %10.0f %s ", real_time, timeLabel,
|
||||||
cpu_time, timeLabel);
|
cpu_time, timeLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!result.report_big_o && !result.report_rms) {
|
if (!result.report_big_o && !result.report_rms) {
|
||||||
|
|
|
@ -31,38 +31,28 @@ namespace benchmark {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
std::vector<std::string> elements = {
|
std::vector<std::string> elements = {
|
||||||
"name",
|
"name", "iterations", "real_time", "cpu_time",
|
||||||
"iterations",
|
"time_unit", "bytes_per_second", "items_per_second", "label",
|
||||||
"real_time",
|
"error_occurred", "error_message"};
|
||||||
"cpu_time",
|
|
||||||
"time_unit",
|
|
||||||
"bytes_per_second",
|
|
||||||
"items_per_second",
|
|
||||||
"label",
|
|
||||||
"error_occurred",
|
|
||||||
"error_message"
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CSVReporter::ReportContext(const Context& context) {
|
bool CSVReporter::ReportContext(const Context& context) {
|
||||||
PrintBasicContext(&GetErrorStream(), context);
|
PrintBasicContext(&GetErrorStream(), context);
|
||||||
|
|
||||||
std::ostream& Out = GetOutputStream();
|
std::ostream& Out = GetOutputStream();
|
||||||
for (auto B = elements.begin(); B != elements.end(); ) {
|
for (auto B = elements.begin(); B != elements.end();) {
|
||||||
Out << *B++;
|
Out << *B++;
|
||||||
if (B != elements.end())
|
if (B != elements.end()) Out << ",";
|
||||||
Out << ",";
|
|
||||||
}
|
}
|
||||||
Out << "\n";
|
Out << "\n";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVReporter::ReportRuns(const std::vector<Run> & reports) {
|
void CSVReporter::ReportRuns(const std::vector<Run>& reports) {
|
||||||
for (const auto& run : reports)
|
for (const auto& run : reports) PrintRunData(run);
|
||||||
PrintRunData(run);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVReporter::PrintRunData(const Run & run) {
|
void CSVReporter::PrintRunData(const Run& run) {
|
||||||
std::ostream& Out = GetOutputStream();
|
std::ostream& Out = GetOutputStream();
|
||||||
|
|
||||||
// Field with embedded double-quote characters must be doubled and the field
|
// Field with embedded double-quote characters must be doubled and the field
|
||||||
|
|
|
@ -4,40 +4,39 @@
|
||||||
#include "benchmark/macros.h"
|
#include "benchmark/macros.h"
|
||||||
|
|
||||||
#ifndef __has_feature
|
#ifndef __has_feature
|
||||||
# define __has_feature(x) 0
|
#define __has_feature(x) 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
# define COMPILER_CLANG
|
#define COMPILER_CLANG
|
||||||
#elif defined(_MSC_VER)
|
#elif defined(_MSC_VER)
|
||||||
# define COMPILER_MSVC
|
#define COMPILER_MSVC
|
||||||
#elif defined(__GNUC__)
|
#elif defined(__GNUC__)
|
||||||
# define COMPILER_GCC
|
#define COMPILER_GCC
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if __has_feature(cxx_attributes)
|
#if __has_feature(cxx_attributes)
|
||||||
# define BENCHMARK_NORETURN [[noreturn]]
|
#define BENCHMARK_NORETURN [[noreturn]]
|
||||||
#elif defined(__GNUC__)
|
#elif defined(__GNUC__)
|
||||||
# define BENCHMARK_NORETURN __attribute__((noreturn))
|
#define BENCHMARK_NORETURN __attribute__((noreturn))
|
||||||
#elif defined(COMPILER_MSVC)
|
#elif defined(COMPILER_MSVC)
|
||||||
# define BENCHMARK_NORETURN __declspec(noreturn)
|
#define BENCHMARK_NORETURN __declspec(noreturn)
|
||||||
#else
|
#else
|
||||||
# define BENCHMARK_NORETURN
|
#define BENCHMARK_NORETURN
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__CYGWIN__)
|
#if defined(__CYGWIN__)
|
||||||
# define BENCHMARK_OS_CYGWIN 1
|
#define BENCHMARK_OS_CYGWIN 1
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
# define BENCHMARK_OS_WINDOWS 1
|
#define BENCHMARK_OS_WINDOWS 1
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
// TODO(ericwf) This doesn't actually check that it is a Mac OSX system. Just
|
// TODO(ericwf) This doesn't actually check that it is a Mac OSX system. Just
|
||||||
// that it is an apple system.
|
// that it is an apple system.
|
||||||
# define BENCHMARK_OS_MACOSX 1
|
#define BENCHMARK_OS_MACOSX 1
|
||||||
#elif defined(__FreeBSD__)
|
#elif defined(__FreeBSD__)
|
||||||
# define BENCHMARK_OS_FREEBSD 1
|
#define BENCHMARK_OS_FREEBSD 1
|
||||||
#elif defined(__linux__)
|
#elif defined(__linux__)
|
||||||
# define BENCHMARK_OS_LINUX 1
|
#define BENCHMARK_OS_LINUX 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif // BENCHMARK_INTERNAL_MACROS_H_
|
||||||
#endif // BENCHMARK_INTERNAL_MACROS_H_
|
|
||||||
|
|
|
@ -47,11 +47,9 @@ std::string FormatKV(std::string const& key, int64_t value) {
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t RoundDouble(double v) {
|
int64_t RoundDouble(double v) { return static_cast<int64_t>(v + 0.5); }
|
||||||
return static_cast<int64_t>(v + 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end namespace
|
} // end namespace
|
||||||
|
|
||||||
bool JSONReporter::ReportContext(const Context& context) {
|
bool JSONReporter::ReportContext(const Context& context) {
|
||||||
std::ostream& out = GetOutputStream();
|
std::ostream& out = GetOutputStream();
|
||||||
|
@ -66,14 +64,11 @@ bool JSONReporter::ReportContext(const Context& context) {
|
||||||
std::string walltime_value = LocalDateTimeString();
|
std::string walltime_value = LocalDateTimeString();
|
||||||
out << indent << FormatKV("date", walltime_value) << ",\n";
|
out << indent << FormatKV("date", walltime_value) << ",\n";
|
||||||
|
|
||||||
out << indent
|
out << indent << FormatKV("num_cpus", static_cast<int64_t>(context.num_cpus))
|
||||||
<< FormatKV("num_cpus", static_cast<int64_t>(context.num_cpus))
|
|
||||||
<< ",\n";
|
<< ",\n";
|
||||||
out << indent
|
out << indent << FormatKV("mhz_per_cpu", RoundDouble(context.mhz_per_cpu))
|
||||||
<< FormatKV("mhz_per_cpu", RoundDouble(context.mhz_per_cpu))
|
|
||||||
<< ",\n";
|
<< ",\n";
|
||||||
out << indent
|
out << indent << FormatKV("cpu_scaling_enabled", context.cpu_scaling_enabled)
|
||||||
<< FormatKV("cpu_scaling_enabled", context.cpu_scaling_enabled)
|
|
||||||
<< ",\n";
|
<< ",\n";
|
||||||
|
|
||||||
#if defined(NDEBUG)
|
#if defined(NDEBUG)
|
||||||
|
@ -118,28 +113,20 @@ void JSONReporter::Finalize() {
|
||||||
void JSONReporter::PrintRunData(Run const& run) {
|
void JSONReporter::PrintRunData(Run const& run) {
|
||||||
std::string indent(6, ' ');
|
std::string indent(6, ' ');
|
||||||
std::ostream& out = GetOutputStream();
|
std::ostream& out = GetOutputStream();
|
||||||
out << indent
|
out << indent << FormatKV("name", run.benchmark_name) << ",\n";
|
||||||
<< FormatKV("name", run.benchmark_name)
|
if (run.error_occurred) {
|
||||||
<< ",\n";
|
out << indent << FormatKV("error_occurred", run.error_occurred) << ",\n";
|
||||||
if (run.error_occurred) {
|
out << indent << FormatKV("error_message", run.error_message) << ",\n";
|
||||||
out << indent
|
}
|
||||||
<< FormatKV("error_occurred", run.error_occurred)
|
|
||||||
<< ",\n";
|
|
||||||
out << indent
|
|
||||||
<< FormatKV("error_message", run.error_message)
|
|
||||||
<< ",\n";
|
|
||||||
}
|
|
||||||
if (!run.report_big_o && !run.report_rms) {
|
if (!run.report_big_o && !run.report_rms) {
|
||||||
out << indent
|
out << indent << FormatKV("iterations", run.iterations) << ",\n";
|
||||||
<< FormatKV("iterations", run.iterations)
|
out << indent
|
||||||
<< ",\n";
|
<< FormatKV("real_time", RoundDouble(run.GetAdjustedRealTime()))
|
||||||
out << indent
|
<< ",\n";
|
||||||
<< FormatKV("real_time", RoundDouble(run.GetAdjustedRealTime()))
|
out << indent
|
||||||
<< ",\n";
|
<< FormatKV("cpu_time", RoundDouble(run.GetAdjustedCPUTime()));
|
||||||
out << indent
|
out << ",\n"
|
||||||
<< FormatKV("cpu_time", RoundDouble(run.GetAdjustedCPUTime()));
|
<< indent << FormatKV("time_unit", GetTimeUnitString(run.time_unit));
|
||||||
out << ",\n" << indent
|
|
||||||
<< FormatKV("time_unit", GetTimeUnitString(run.time_unit));
|
|
||||||
} else if (run.report_big_o) {
|
} else if (run.report_big_o) {
|
||||||
out << indent
|
out << indent
|
||||||
<< FormatKV("cpu_coefficient", RoundDouble(run.GetAdjustedCPUTime()))
|
<< FormatKV("cpu_coefficient", RoundDouble(run.GetAdjustedCPUTime()))
|
||||||
|
@ -147,15 +134,11 @@ void JSONReporter::PrintRunData(Run const& run) {
|
||||||
out << indent
|
out << indent
|
||||||
<< FormatKV("real_coefficient", RoundDouble(run.GetAdjustedRealTime()))
|
<< FormatKV("real_coefficient", RoundDouble(run.GetAdjustedRealTime()))
|
||||||
<< ",\n";
|
<< ",\n";
|
||||||
|
out << indent << FormatKV("big_o", GetBigOString(run.complexity)) << ",\n";
|
||||||
|
out << indent << FormatKV("time_unit", GetTimeUnitString(run.time_unit));
|
||||||
|
} else if (run.report_rms) {
|
||||||
out << indent
|
out << indent
|
||||||
<< FormatKV("big_o", GetBigOString(run.complexity))
|
<< FormatKV("rms", RoundDouble(run.GetAdjustedCPUTime() * 100)) << '%';
|
||||||
<< ",\n";
|
|
||||||
out << indent
|
|
||||||
<< FormatKV("time_unit", GetTimeUnitString(run.time_unit));
|
|
||||||
} else if(run.report_rms) {
|
|
||||||
out << indent
|
|
||||||
<< FormatKV("rms", RoundDouble(run.GetAdjustedCPUTime()*100))
|
|
||||||
<< '%';
|
|
||||||
}
|
}
|
||||||
if (run.bytes_per_second > 0.0) {
|
if (run.bytes_per_second > 0.0) {
|
||||||
out << ",\n"
|
out << ",\n"
|
||||||
|
@ -168,9 +151,7 @@ void JSONReporter::PrintRunData(Run const& run) {
|
||||||
<< FormatKV("items_per_second", RoundDouble(run.items_per_second));
|
<< FormatKV("items_per_second", RoundDouble(run.items_per_second));
|
||||||
}
|
}
|
||||||
if (!run.report_label.empty()) {
|
if (!run.report_label.empty()) {
|
||||||
out << ",\n"
|
out << ",\n" << indent << FormatKV("label", run.report_label);
|
||||||
<< indent
|
|
||||||
<< FormatKV("label", run.report_label);
|
|
||||||
}
|
}
|
||||||
out << '\n';
|
out << '\n';
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,10 +63,11 @@ inline LogType& GetLogInstanceForLevel(int level) {
|
||||||
return GetNullLogInstance();
|
return GetNullLogInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end namespace internal
|
} // end namespace internal
|
||||||
} // end namespace benchmark
|
} // end namespace benchmark
|
||||||
|
|
||||||
#define VLOG(x) (::benchmark::internal::GetLogInstanceForLevel(x) \
|
#define VLOG(x) \
|
||||||
<< "-- LOG(" << x << "): ")
|
(::benchmark::internal::GetLogInstanceForLevel(x) << "-- LOG(" << x << "):" \
|
||||||
|
" ")
|
||||||
|
|
||||||
#endif
|
#endif
|
57
src/mutex.h
57
src/mutex.h
|
@ -1,30 +1,26 @@
|
||||||
#ifndef BENCHMARK_MUTEX_H_
|
#ifndef BENCHMARK_MUTEX_H_
|
||||||
#define BENCHMARK_MUTEX_H_
|
#define BENCHMARK_MUTEX_H_
|
||||||
|
|
||||||
#include <mutex>
|
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
|
|
||||||
// Enable thread safety attributes only with clang.
|
// Enable thread safety attributes only with clang.
|
||||||
// The attributes can be safely erased when compiling with other compilers.
|
// The attributes can be safely erased when compiling with other compilers.
|
||||||
#if defined(HAVE_THREAD_SAFETY_ATTRIBUTES)
|
#if defined(HAVE_THREAD_SAFETY_ATTRIBUTES)
|
||||||
#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
|
#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
|
||||||
#else
|
#else
|
||||||
#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op
|
#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define CAPABILITY(x) \
|
#define CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(capability(x))
|
||||||
THREAD_ANNOTATION_ATTRIBUTE__(capability(x))
|
|
||||||
|
|
||||||
#define SCOPED_CAPABILITY \
|
#define SCOPED_CAPABILITY THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
|
||||||
THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
|
|
||||||
|
|
||||||
#define GUARDED_BY(x) \
|
#define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
|
||||||
THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
|
|
||||||
|
|
||||||
#define PT_GUARDED_BY(x) \
|
#define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x))
|
||||||
THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x))
|
|
||||||
|
|
||||||
#define ACQUIRED_BEFORE(...) \
|
#define ACQUIRED_BEFORE(...) \
|
||||||
THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__))
|
THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__))
|
||||||
|
@ -56,22 +52,18 @@
|
||||||
#define TRY_ACQUIRE_SHARED(...) \
|
#define TRY_ACQUIRE_SHARED(...) \
|
||||||
THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__))
|
THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__))
|
||||||
|
|
||||||
#define EXCLUDES(...) \
|
#define EXCLUDES(...) THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))
|
||||||
THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))
|
|
||||||
|
|
||||||
#define ASSERT_CAPABILITY(x) \
|
#define ASSERT_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x))
|
||||||
THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x))
|
|
||||||
|
|
||||||
#define ASSERT_SHARED_CAPABILITY(x) \
|
#define ASSERT_SHARED_CAPABILITY(x) \
|
||||||
THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x))
|
THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x))
|
||||||
|
|
||||||
#define RETURN_CAPABILITY(x) \
|
#define RETURN_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
|
||||||
THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
|
|
||||||
|
|
||||||
#define NO_THREAD_SAFETY_ANALYSIS \
|
#define NO_THREAD_SAFETY_ANALYSIS \
|
||||||
THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
|
THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
|
||||||
|
|
||||||
|
|
||||||
namespace benchmark {
|
namespace benchmark {
|
||||||
|
|
||||||
typedef std::condition_variable Condition;
|
typedef std::condition_variable Condition;
|
||||||
|
@ -80,30 +72,27 @@ typedef std::condition_variable Condition;
|
||||||
// we can annotate them with thread safety attributes and use the
|
// we can annotate them with thread safety attributes and use the
|
||||||
// -Wthread-safety warning with clang. The standard library types cannot be
|
// -Wthread-safety warning with clang. The standard library types cannot be
|
||||||
// used directly because they do not provided the required annotations.
|
// used directly because they do not provided the required annotations.
|
||||||
class CAPABILITY("mutex") Mutex
|
class CAPABILITY("mutex") Mutex {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
Mutex() {}
|
Mutex() {}
|
||||||
|
|
||||||
void lock() ACQUIRE() { mut_.lock(); }
|
void lock() ACQUIRE() { mut_.lock(); }
|
||||||
void unlock() RELEASE() { mut_.unlock(); }
|
void unlock() RELEASE() { mut_.unlock(); }
|
||||||
std::mutex& native_handle() {
|
std::mutex& native_handle() { return mut_; }
|
||||||
return mut_;
|
|
||||||
}
|
private:
|
||||||
private:
|
|
||||||
std::mutex mut_;
|
std::mutex mut_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SCOPED_CAPABILITY MutexLock {
|
||||||
class SCOPED_CAPABILITY MutexLock
|
|
||||||
{
|
|
||||||
typedef std::unique_lock<std::mutex> MutexLockImp;
|
typedef std::unique_lock<std::mutex> MutexLockImp;
|
||||||
public:
|
|
||||||
MutexLock(Mutex& m) ACQUIRE(m) : ml_(m.native_handle())
|
public:
|
||||||
{ }
|
MutexLock(Mutex& m) ACQUIRE(m) : ml_(m.native_handle()) {}
|
||||||
~MutexLock() RELEASE() {}
|
~MutexLock() RELEASE() {}
|
||||||
MutexLockImp& native_handle() { return ml_; }
|
MutexLockImp& native_handle() { return ml_; }
|
||||||
private:
|
|
||||||
|
private:
|
||||||
MutexLockImp ml_;
|
MutexLockImp ml_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -161,6 +150,6 @@ class Barrier {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace benchmark
|
} // end namespace benchmark
|
||||||
|
|
||||||
#endif // BENCHMARK_MUTEX_H_
|
#endif // BENCHMARK_MUTEX_H_
|
||||||
|
|
10
src/re.h
10
src/re.h
|
@ -46,19 +46,19 @@ class Regex {
|
||||||
|
|
||||||
// Returns whether str matches the compiled regular expression.
|
// Returns whether str matches the compiled regular expression.
|
||||||
bool Match(const std::string& str);
|
bool Match(const std::string& str);
|
||||||
private:
|
|
||||||
|
private:
|
||||||
bool init_;
|
bool init_;
|
||||||
// Underlying regular expression object
|
// Underlying regular expression object
|
||||||
#if defined(HAVE_STD_REGEX)
|
#if defined(HAVE_STD_REGEX)
|
||||||
std::regex re_;
|
std::regex re_;
|
||||||
#elif defined(HAVE_POSIX_REGEX) || defined(HAVE_GNU_POSIX_REGEX)
|
#elif defined(HAVE_POSIX_REGEX) || defined(HAVE_GNU_POSIX_REGEX)
|
||||||
regex_t re_;
|
regex_t re_;
|
||||||
#else
|
#else
|
||||||
# error No regular expression backend implementation available
|
#error No regular expression backend implementation available
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#if defined(HAVE_STD_REGEX)
|
#if defined(HAVE_STD_REGEX)
|
||||||
|
|
||||||
inline bool Regex::Init(const std::string& spec, std::string* error) {
|
inline bool Regex::Init(const std::string& spec, std::string* error) {
|
||||||
|
@ -74,7 +74,7 @@ inline bool Regex::Init(const std::string& spec, std::string* error) {
|
||||||
return init_;
|
return init_;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Regex::~Regex() { }
|
inline Regex::~Regex() {}
|
||||||
|
|
||||||
inline bool Regex::Match(const std::string& str) {
|
inline bool Regex::Match(const std::string& str) {
|
||||||
if (!init_) {
|
if (!init_) {
|
||||||
|
|
|
@ -18,8 +18,8 @@
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
#include "stat.h"
|
#include "stat.h"
|
||||||
|
@ -27,49 +27,42 @@
|
||||||
namespace benchmark {
|
namespace benchmark {
|
||||||
|
|
||||||
BenchmarkReporter::BenchmarkReporter()
|
BenchmarkReporter::BenchmarkReporter()
|
||||||
: output_stream_(&std::cout), error_stream_(&std::cerr)
|
: output_stream_(&std::cout), error_stream_(&std::cerr) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
BenchmarkReporter::~BenchmarkReporter() {
|
BenchmarkReporter::~BenchmarkReporter() {}
|
||||||
}
|
|
||||||
|
|
||||||
void BenchmarkReporter::PrintBasicContext(std::ostream *out_ptr,
|
void BenchmarkReporter::PrintBasicContext(std::ostream *out_ptr,
|
||||||
Context const &context) {
|
Context const &context) {
|
||||||
CHECK(out_ptr) << "cannot be null";
|
CHECK(out_ptr) << "cannot be null";
|
||||||
auto& Out = *out_ptr;
|
auto &Out = *out_ptr;
|
||||||
|
|
||||||
Out << "Run on (" << context.num_cpus << " X " << context.mhz_per_cpu
|
Out << "Run on (" << context.num_cpus << " X " << context.mhz_per_cpu
|
||||||
<< " MHz CPU " << ((context.num_cpus > 1) ? "s" : "") << ")\n";
|
<< " MHz CPU " << ((context.num_cpus > 1) ? "s" : "") << ")\n";
|
||||||
|
|
||||||
Out << LocalDateTimeString() << "\n";
|
Out << LocalDateTimeString() << "\n";
|
||||||
|
|
||||||
if (context.cpu_scaling_enabled) {
|
if (context.cpu_scaling_enabled) {
|
||||||
Out << "***WARNING*** CPU scaling is enabled, the benchmark "
|
Out << "***WARNING*** CPU scaling is enabled, the benchmark "
|
||||||
"real time measurements may be noisy and will incur extra "
|
"real time measurements may be noisy and will incur extra "
|
||||||
"overhead.\n";
|
"overhead.\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
Out << "***WARNING*** Library was built as DEBUG. Timings may be "
|
Out << "***WARNING*** Library was built as DEBUG. Timings may be "
|
||||||
"affected.\n";
|
"affected.\n";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
double BenchmarkReporter::Run::GetAdjustedRealTime() const {
|
double BenchmarkReporter::Run::GetAdjustedRealTime() const {
|
||||||
double new_time = real_accumulated_time * GetTimeUnitMultiplier(time_unit);
|
double new_time = real_accumulated_time * GetTimeUnitMultiplier(time_unit);
|
||||||
if (iterations != 0)
|
if (iterations != 0) new_time /= static_cast<double>(iterations);
|
||||||
new_time /= static_cast<double>(iterations);
|
|
||||||
return new_time;
|
return new_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
double BenchmarkReporter::Run::GetAdjustedCPUTime() const {
|
double BenchmarkReporter::Run::GetAdjustedCPUTime() const {
|
||||||
double new_time = cpu_accumulated_time * GetTimeUnitMultiplier(time_unit);
|
double new_time = cpu_accumulated_time * GetTimeUnitMultiplier(time_unit);
|
||||||
if (iterations != 0)
|
if (iterations != 0) new_time /= static_cast<double>(iterations);
|
||||||
new_time /= static_cast<double>(iterations);
|
|
||||||
return new_time;
|
return new_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // end namespace benchmark
|
||||||
|
|
||||||
} // end namespace benchmark
|
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
|
|
||||||
namespace benchmark {
|
namespace benchmark {
|
||||||
|
|
||||||
template <typename VType, typename NumType>
|
template <typename VType, typename NumType>
|
||||||
|
@ -136,7 +135,7 @@ class Stat1 {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static_assert(std::is_integral<NumType>::value &&
|
static_assert(std::is_integral<NumType>::value &&
|
||||||
!std::is_same<NumType, bool>::value,
|
!std::is_same<NumType, bool>::value,
|
||||||
"NumType must be an integral type that is not bool.");
|
"NumType must be an integral type that is not bool.");
|
||||||
// Let i be the index of the samples provided (using +=)
|
// Let i be the index of the samples provided (using +=)
|
||||||
// and weight[i],value[i] be the data of sample #i
|
// and weight[i],value[i] be the data of sample #i
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
#include "string_util.h"
|
#include "string_util.h"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
#include <array>
|
#include <cstdio>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "arraysize.h"
|
#include "arraysize.h"
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ static_assert(arraysize(kSmallSIUnits) == arraysize(kBigSIUnits),
|
||||||
|
|
||||||
static const int64_t kUnitsSize = arraysize(kBigSIUnits);
|
static const int64_t kUnitsSize = arraysize(kBigSIUnits);
|
||||||
|
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
|
||||||
void ToExponentAndMantissa(double val, double thresh, int precision,
|
void ToExponentAndMantissa(double val, double thresh, int precision,
|
||||||
double one_k, std::string* mantissa,
|
double one_k, std::string* mantissa,
|
||||||
|
@ -118,8 +118,7 @@ std::string HumanReadableNumber(double n) {
|
||||||
return ToBinaryStringFullySpecified(n, 1.1, 1);
|
return ToBinaryStringFullySpecified(n, 1.1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string StringPrintFImp(const char *msg, va_list args)
|
std::string StringPrintFImp(const char* msg, va_list args) {
|
||||||
{
|
|
||||||
// we might need a second shot at this, so pre-emptivly make a copy
|
// we might need a second shot at this, so pre-emptivly make a copy
|
||||||
va_list args_cp;
|
va_list args_cp;
|
||||||
va_copy(args_cp, args);
|
va_copy(args_cp, args);
|
||||||
|
@ -128,14 +127,14 @@ std::string StringPrintFImp(const char *msg, va_list args)
|
||||||
// allocation guess what the size might be
|
// allocation guess what the size might be
|
||||||
std::array<char, 256> local_buff;
|
std::array<char, 256> local_buff;
|
||||||
std::size_t size = local_buff.size();
|
std::size_t size = local_buff.size();
|
||||||
// 2015-10-08: vsnprintf is used instead of snd::vsnprintf due to a limitation in the android-ndk
|
// 2015-10-08: vsnprintf is used instead of snd::vsnprintf due to a limitation
|
||||||
|
// in the android-ndk
|
||||||
auto ret = vsnprintf(local_buff.data(), size, msg, args_cp);
|
auto ret = vsnprintf(local_buff.data(), size, msg, args_cp);
|
||||||
|
|
||||||
va_end(args_cp);
|
va_end(args_cp);
|
||||||
|
|
||||||
// handle empty expansion
|
// handle empty expansion
|
||||||
if (ret == 0)
|
if (ret == 0) return std::string{};
|
||||||
return std::string{};
|
|
||||||
if (static_cast<std::size_t>(ret) < size)
|
if (static_cast<std::size_t>(ret) < size)
|
||||||
return std::string(local_buff.data());
|
return std::string(local_buff.data());
|
||||||
|
|
||||||
|
@ -143,13 +142,13 @@ std::string StringPrintFImp(const char *msg, va_list args)
|
||||||
// add 1 to size to account for null-byte in size cast to prevent overflow
|
// add 1 to size to account for null-byte in size cast to prevent overflow
|
||||||
size = static_cast<std::size_t>(ret) + 1;
|
size = static_cast<std::size_t>(ret) + 1;
|
||||||
auto buff_ptr = std::unique_ptr<char[]>(new char[size]);
|
auto buff_ptr = std::unique_ptr<char[]>(new char[size]);
|
||||||
// 2015-10-08: vsnprintf is used instead of snd::vsnprintf due to a limitation in the android-ndk
|
// 2015-10-08: vsnprintf is used instead of snd::vsnprintf due to a limitation
|
||||||
|
// in the android-ndk
|
||||||
ret = vsnprintf(buff_ptr.get(), size, msg, args);
|
ret = vsnprintf(buff_ptr.get(), size, msg, args);
|
||||||
return std::string(buff_ptr.get());
|
return std::string(buff_ptr.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string StringPrintF(const char* format, ...)
|
std::string StringPrintF(const char* format, ...) {
|
||||||
{
|
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
std::string tmp = StringPrintFImp(format, args);
|
std::string tmp = StringPrintFImp(format, args);
|
||||||
|
@ -160,10 +159,10 @@ std::string StringPrintF(const char* format, ...)
|
||||||
void ReplaceAll(std::string* str, const std::string& from,
|
void ReplaceAll(std::string* str, const std::string& from,
|
||||||
const std::string& to) {
|
const std::string& to) {
|
||||||
std::size_t start = 0;
|
std::size_t start = 0;
|
||||||
while((start = str->find(from, start)) != std::string::npos) {
|
while ((start = str->find(from, start)) != std::string::npos) {
|
||||||
str->replace(start, from.length(), to);
|
str->replace(start, from.length(), to);
|
||||||
start += to.length();
|
start += to.length();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end namespace benchmark
|
} // end namespace benchmark
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#ifndef BENCHMARK_STRING_UTIL_H_
|
#ifndef BENCHMARK_STRING_UTIL_H_
|
||||||
#define BENCHMARK_STRING_UTIL_H_
|
#define BENCHMARK_STRING_UTIL_H_
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include "internal_macros.h"
|
#include "internal_macros.h"
|
||||||
|
|
||||||
|
@ -14,23 +14,19 @@ std::string HumanReadableNumber(double n);
|
||||||
|
|
||||||
std::string StringPrintF(const char* format, ...);
|
std::string StringPrintF(const char* format, ...);
|
||||||
|
|
||||||
inline std::ostream&
|
inline std::ostream& StringCatImp(std::ostream& out) BENCHMARK_NOEXCEPT {
|
||||||
StringCatImp(std::ostream& out) BENCHMARK_NOEXCEPT
|
|
||||||
{
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class First, class ...Rest>
|
template <class First, class... Rest>
|
||||||
inline std::ostream&
|
inline std::ostream& StringCatImp(std::ostream& out, First&& f,
|
||||||
StringCatImp(std::ostream& out, First&& f, Rest&&... rest)
|
Rest&&... rest) {
|
||||||
{
|
|
||||||
out << std::forward<First>(f);
|
out << std::forward<First>(f);
|
||||||
return StringCatImp(out, std::forward<Rest>(rest)...);
|
return StringCatImp(out, std::forward<Rest>(rest)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class ...Args>
|
template <class... Args>
|
||||||
inline std::string StrCat(Args&&... args)
|
inline std::string StrCat(Args&&... args) {
|
||||||
{
|
|
||||||
std::ostringstream ss;
|
std::ostringstream ss;
|
||||||
StringCatImp(ss, std::forward<Args>(args)...);
|
StringCatImp(ss, std::forward<Args>(args)...);
|
||||||
return ss.str();
|
return ss.str();
|
||||||
|
@ -39,6 +35,6 @@ inline std::string StrCat(Args&&... args)
|
||||||
void ReplaceAll(std::string* str, const std::string& from,
|
void ReplaceAll(std::string* str, const std::string& from,
|
||||||
const std::string& to);
|
const std::string& to);
|
||||||
|
|
||||||
} // end namespace benchmark
|
} // end namespace benchmark
|
||||||
|
|
||||||
#endif // BENCHMARK_STRING_UTIL_H_
|
#endif // BENCHMARK_STRING_UTIL_H_
|
||||||
|
|
|
@ -17,13 +17,13 @@
|
||||||
|
|
||||||
#ifdef BENCHMARK_OS_WINDOWS
|
#ifdef BENCHMARK_OS_WINDOWS
|
||||||
#include <Shlwapi.h>
|
#include <Shlwapi.h>
|
||||||
#include <Windows.h>
|
|
||||||
#include <VersionHelpers.h>
|
#include <VersionHelpers.h>
|
||||||
|
#include <Windows.h>
|
||||||
#else
|
#else
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#include <sys/types.h> // this header must be included before 'sys/sysctl.h' to avoid compilation error on FreeBSD
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h> // this header must be included before 'sys/sysctl.h' to avoid compilation error on FreeBSD
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#if defined BENCHMARK_OS_FREEBSD || defined BENCHMARK_OS_MACOSX
|
#if defined BENCHMARK_OS_FREEBSD || defined BENCHMARK_OS_MACOSX
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
|
@ -31,8 +31,8 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <cstdio>
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
@ -126,7 +126,8 @@ void InitializeSystemInfo() {
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
perror(pname);
|
perror(pname);
|
||||||
if (!saw_mhz) {
|
if (!saw_mhz) {
|
||||||
cpuinfo_cycles_per_second = static_cast<double>(EstimateCyclesPerSecond());
|
cpuinfo_cycles_per_second =
|
||||||
|
static_cast<double>(EstimateCyclesPerSecond());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -196,7 +197,8 @@ void InitializeSystemInfo() {
|
||||||
cpuinfo_cycles_per_second = bogo_clock;
|
cpuinfo_cycles_per_second = bogo_clock;
|
||||||
} else {
|
} else {
|
||||||
// If we don't even have bogomips, we'll use the slow estimation.
|
// If we don't even have bogomips, we'll use the slow estimation.
|
||||||
cpuinfo_cycles_per_second = static_cast<double>(EstimateCyclesPerSecond());
|
cpuinfo_cycles_per_second =
|
||||||
|
static_cast<double>(EstimateCyclesPerSecond());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (num_cpus == 0) {
|
if (num_cpus == 0) {
|
||||||
|
@ -238,7 +240,6 @@ void InitializeSystemInfo() {
|
||||||
}
|
}
|
||||||
// TODO: also figure out cpuinfo_num_cpus
|
// TODO: also figure out cpuinfo_num_cpus
|
||||||
|
|
||||||
|
|
||||||
#elif defined BENCHMARK_OS_WINDOWS
|
#elif defined BENCHMARK_OS_WINDOWS
|
||||||
// In NT, read MHz from the registry. If we fail to do so or we're in win9x
|
// In NT, read MHz from the registry. If we fail to do so or we're in win9x
|
||||||
// then make a crude estimate.
|
// then make a crude estimate.
|
||||||
|
@ -248,15 +249,19 @@ void InitializeSystemInfo() {
|
||||||
SHGetValueA(HKEY_LOCAL_MACHINE,
|
SHGetValueA(HKEY_LOCAL_MACHINE,
|
||||||
"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",
|
"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",
|
||||||
"~MHz", nullptr, &data, &data_size)))
|
"~MHz", nullptr, &data, &data_size)))
|
||||||
cpuinfo_cycles_per_second = static_cast<double>((int64_t)data * (int64_t)(1000 * 1000)); // was mhz
|
cpuinfo_cycles_per_second =
|
||||||
|
static_cast<double>((int64_t)data * (int64_t)(1000 * 1000)); // was mhz
|
||||||
else
|
else
|
||||||
cpuinfo_cycles_per_second = static_cast<double>(EstimateCyclesPerSecond());
|
cpuinfo_cycles_per_second = static_cast<double>(EstimateCyclesPerSecond());
|
||||||
|
|
||||||
SYSTEM_INFO sysinfo;
|
SYSTEM_INFO sysinfo;
|
||||||
// Use memset as opposed to = {} to avoid GCC missing initializer false positives.
|
// Use memset as opposed to = {} to avoid GCC missing initializer false
|
||||||
|
// positives.
|
||||||
std::memset(&sysinfo, 0, sizeof(SYSTEM_INFO));
|
std::memset(&sysinfo, 0, sizeof(SYSTEM_INFO));
|
||||||
GetSystemInfo(&sysinfo);
|
GetSystemInfo(&sysinfo);
|
||||||
cpuinfo_num_cpus = sysinfo.dwNumberOfProcessors; // number of logical processors in the current group
|
cpuinfo_num_cpus = sysinfo.dwNumberOfProcessors; // number of logical
|
||||||
|
// processors in the current
|
||||||
|
// group
|
||||||
|
|
||||||
#elif defined BENCHMARK_OS_MACOSX
|
#elif defined BENCHMARK_OS_MACOSX
|
||||||
// returning "mach time units" per second. the current number of elapsed
|
// returning "mach time units" per second. the current number of elapsed
|
||||||
|
@ -277,8 +282,8 @@ void InitializeSystemInfo() {
|
||||||
int num_cpus = 0;
|
int num_cpus = 0;
|
||||||
size_t size = sizeof(num_cpus);
|
size_t size = sizeof(num_cpus);
|
||||||
int numcpus_name[] = {CTL_HW, HW_NCPU};
|
int numcpus_name[] = {CTL_HW, HW_NCPU};
|
||||||
if (::sysctl(numcpus_name, arraysize(numcpus_name), &num_cpus, &size, nullptr, 0) ==
|
if (::sysctl(numcpus_name, arraysize(numcpus_name), &num_cpus, &size, nullptr,
|
||||||
0 &&
|
0) == 0 &&
|
||||||
(size == sizeof(num_cpus)))
|
(size == sizeof(num_cpus)))
|
||||||
cpuinfo_num_cpus = num_cpus;
|
cpuinfo_num_cpus = num_cpus;
|
||||||
|
|
||||||
|
@ -316,8 +321,8 @@ bool CpuScalingEnabled() {
|
||||||
// local file system. If reading the exported files fails, then we may not be
|
// local file system. If reading the exported files fails, then we may not be
|
||||||
// running on Linux, so we silently ignore all the read errors.
|
// running on Linux, so we silently ignore all the read errors.
|
||||||
for (int cpu = 0, num_cpus = NumCPUs(); cpu < num_cpus; ++cpu) {
|
for (int cpu = 0, num_cpus = NumCPUs(); cpu < num_cpus; ++cpu) {
|
||||||
std::string governor_file = StrCat("/sys/devices/system/cpu/cpu", cpu,
|
std::string governor_file =
|
||||||
"/cpufreq/scaling_governor");
|
StrCat("/sys/devices/system/cpu/cpu", cpu, "/cpufreq/scaling_governor");
|
||||||
FILE* file = fopen(governor_file.c_str(), "r");
|
FILE* file = fopen(governor_file.c_str(), "r");
|
||||||
if (!file) break;
|
if (!file) break;
|
||||||
char buff[16];
|
char buff[16];
|
||||||
|
|
|
@ -92,16 +92,16 @@ double MakeTime(struct timespec const& ts) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
BENCHMARK_NORETURN static void DiagnoseAndExit(const char* msg) {
|
BENCHMARK_NORETURN static void DiagnoseAndExit(const char* msg) {
|
||||||
std::cerr << "ERROR: " << msg << std::endl;
|
std::cerr << "ERROR: " << msg << std::endl;
|
||||||
std::exit(EXIT_FAILURE);
|
std::exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end namespace
|
} // end namespace
|
||||||
|
|
||||||
|
|
||||||
double ProcessCPUUsage() {
|
double ProcessCPUUsage() {
|
||||||
// FIXME We want to use clock_gettime, but its not available in MacOS 10.11. See https://github.com/google/benchmark/pull/292
|
// FIXME We want to use clock_gettime, but its not available in MacOS 10.11. See
|
||||||
|
// https://github.com/google/benchmark/pull/292
|
||||||
#if defined(CLOCK_PROCESS_CPUTIME_ID) && !defined(BENCHMARK_OS_MACOSX)
|
#if defined(CLOCK_PROCESS_CPUTIME_ID) && !defined(BENCHMARK_OS_MACOSX)
|
||||||
struct timespec spec;
|
struct timespec spec;
|
||||||
if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &spec) == 0)
|
if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &spec) == 0)
|
||||||
|
@ -113,23 +113,23 @@ double ProcessCPUUsage() {
|
||||||
FILETIME exit_time;
|
FILETIME exit_time;
|
||||||
FILETIME kernel_time;
|
FILETIME kernel_time;
|
||||||
FILETIME user_time;
|
FILETIME user_time;
|
||||||
if (GetProcessTimes(proc, &creation_time, &exit_time, &kernel_time, &user_time))
|
if (GetProcessTimes(proc, &creation_time, &exit_time, &kernel_time,
|
||||||
|
&user_time))
|
||||||
return MakeTime(kernel_time, user_time);
|
return MakeTime(kernel_time, user_time);
|
||||||
DiagnoseAndExit("GetProccessTimes() failed");
|
DiagnoseAndExit("GetProccessTimes() failed");
|
||||||
#else
|
#else
|
||||||
struct rusage ru;
|
struct rusage ru;
|
||||||
if (getrusage(RUSAGE_SELF, &ru) == 0)
|
if (getrusage(RUSAGE_SELF, &ru) == 0) return MakeTime(ru);
|
||||||
return MakeTime(ru);
|
|
||||||
DiagnoseAndExit("clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...) failed");
|
DiagnoseAndExit("clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...) failed");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
double ThreadCPUUsage() {
|
double ThreadCPUUsage() {
|
||||||
// FIXME We want to use clock_gettime, but its not available in MacOS 10.11. See https://github.com/google/benchmark/pull/292
|
// FIXME We want to use clock_gettime, but its not available in MacOS 10.11. See
|
||||||
|
// https://github.com/google/benchmark/pull/292
|
||||||
#if defined(CLOCK_THREAD_CPUTIME_ID) && !defined(BENCHMARK_OS_MACOSX)
|
#if defined(CLOCK_THREAD_CPUTIME_ID) && !defined(BENCHMARK_OS_MACOSX)
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) == 0)
|
if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) == 0) return MakeTime(ts);
|
||||||
return MakeTime(ts);
|
|
||||||
DiagnoseAndExit("clock_gettime(CLOCK_THREAD_CPUTIME_ID, ...) failed");
|
DiagnoseAndExit("clock_gettime(CLOCK_THREAD_CPUTIME_ID, ...) failed");
|
||||||
#elif defined(BENCHMARK_OS_WINDOWS)
|
#elif defined(BENCHMARK_OS_WINDOWS)
|
||||||
HANDLE this_thread = GetCurrentThread();
|
HANDLE this_thread = GetCurrentThread();
|
||||||
|
@ -144,8 +144,8 @@ double ThreadCPUUsage() {
|
||||||
mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
|
mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
|
||||||
thread_basic_info_data_t info;
|
thread_basic_info_data_t info;
|
||||||
mach_port_t thread = pthread_mach_thread_np(pthread_self());
|
mach_port_t thread = pthread_mach_thread_np(pthread_self());
|
||||||
if (thread_info(thread, THREAD_BASIC_INFO, (thread_info_t) &info, &count)
|
if (thread_info(thread, THREAD_BASIC_INFO, (thread_info_t)&info, &count) ==
|
||||||
== KERN_SUCCESS) {
|
KERN_SUCCESS) {
|
||||||
return MakeTime(info);
|
return MakeTime(info);
|
||||||
}
|
}
|
||||||
DiagnoseAndExit("ThreadCPUUsage() failed when evaluating thread_info");
|
DiagnoseAndExit("ThreadCPUUsage() failed when evaluating thread_info");
|
||||||
|
|
Loading…
Reference in New Issue