Refactor/modularize headers (#2140)
* Split the benchmark monolithic header
* src uses modular headers
* updated tests to use split headers
* clang-format
* clang-format mistake
* fix exports
* suppress warnings on msvc
* fixing double pops and some more missing exports
diff --git a/BUILD.bazel b/BUILD.bazel
index 993b261..8cad9d6 100644
--- a/BUILD.bazel
+++ b/BUILD.bazel
@@ -49,7 +49,18 @@
),
hdrs = [
"include/benchmark/benchmark.h",
+ "include/benchmark/benchmark_api.h",
+ "include/benchmark/counter.h",
"include/benchmark/export.h",
+ "include/benchmark/macros.h",
+ "include/benchmark/managers.h",
+ "include/benchmark/registration.h",
+ "include/benchmark/reporter.h",
+ "include/benchmark/state.h",
+ "include/benchmark/statistics.h",
+ "include/benchmark/sysinfo.h",
+ "include/benchmark/types.h",
+ "include/benchmark/utils.h",
],
copts = select({
":windows": MSVC_COPTS,
@@ -89,7 +100,18 @@
srcs = ["src/benchmark_main.cc"],
hdrs = [
"include/benchmark/benchmark.h",
+ "include/benchmark/benchmark_api.h",
+ "include/benchmark/counter.h",
"include/benchmark/export.h",
+ "include/benchmark/macros.h",
+ "include/benchmark/managers.h",
+ "include/benchmark/registration.h",
+ "include/benchmark/reporter.h",
+ "include/benchmark/state.h",
+ "include/benchmark/statistics.h",
+ "include/benchmark/sysinfo.h",
+ "include/benchmark/types.h",
+ "include/benchmark/utils.h",
],
includes = ["include"],
visibility = ["//visibility:public"],
diff --git a/README.md b/README.md
index 1d4470e..db99409 100644
--- a/README.md
+++ b/README.md
@@ -11,7 +11,8 @@
A library to benchmark code snippets, similar to unit tests. Example:
```c++
-#include <benchmark/benchmark.h>
+#include <benchmark/registration.h>
+#include <benchmark/state.h>
static void BM_SomeFunction(benchmark::State& state) {
// Perform setup here
diff --git a/include/benchmark/benchmark.h b/include/benchmark/benchmark.h
index 0963e70..e065db3 100644
--- a/include/benchmark/benchmark.h
+++ b/include/benchmark/benchmark.h
@@ -12,2105 +12,19 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// Support for registering benchmarks for functions.
-
-/* Example usage:
-// Define a function that executes the code to be measured a
-// specified number of times:
-static void BM_StringCreation(benchmark::State& state) {
- for (auto _ : state)
- std::string empty_string;
-}
-
-// Register the function as a benchmark
-BENCHMARK(BM_StringCreation);
-
-// Define another benchmark
-static void BM_StringCopy(benchmark::State& state) {
- std::string x = "hello";
- for (auto _ : state)
- std::string copy(x);
-}
-BENCHMARK(BM_StringCopy);
-
-// Augment the main() program to invoke benchmarks if specified
-// via the --benchmark_filter command line flag. E.g.,
-// my_unittest --benchmark_filter=all
-// my_unittest --benchmark_filter=BM_StringCreation
-// my_unittest --benchmark_filter=String
-// my_unittest --benchmark_filter='Copy|Creation'
-int main(int argc, char** argv) {
- benchmark::MaybeReenterWithoutASLR(argc, argv);
- benchmark::Initialize(&argc, argv);
- benchmark::RunSpecifiedBenchmarks();
- benchmark::Shutdown();
- return 0;
-}
-
-// Sometimes a family of microbenchmarks can be implemented with
-// just one routine that takes an extra argument to specify which
-// one of the family of benchmarks to run. For example, the following
-// code defines a family of microbenchmarks for measuring the speed
-// of memcpy() calls of different lengths:
-
-static void BM_memcpy(benchmark::State& state) {
- char* src = new char[state.range(0)]; char* dst = new char[state.range(0)];
- memset(src, 'x', state.range(0));
- for (auto _ : state)
- memcpy(dst, src, state.range(0));
- state.SetBytesProcessed(state.iterations() * state.range(0));
- delete[] src; delete[] dst;
-}
-BENCHMARK(BM_memcpy)->Arg(8)->Arg(64)->Arg(512)->Arg(1<<10)->Arg(8<<10);
-
-// The preceding code is quite repetitive, and can be replaced with the
-// following short-hand. The following invocation will pick a few
-// appropriate arguments in the specified range and will generate a
-// microbenchmark for each such argument.
-BENCHMARK(BM_memcpy)->Range(8, 8<<10);
-
-// You might have a microbenchmark that depends on two inputs. For
-// example, the following code defines a family of microbenchmarks for
-// measuring the speed of set insertion.
-static void BM_SetInsert(benchmark::State& state) {
- set<int> data;
- for (auto _ : state) {
- state.PauseTiming();
- data = ConstructRandomSet(state.range(0));
- state.ResumeTiming();
- for (int j = 0; j < state.range(1); ++j)
- data.insert(RandomNumber());
- }
-}
-BENCHMARK(BM_SetInsert)
- ->Args({1<<10, 128})
- ->Args({2<<10, 128})
- ->Args({4<<10, 128})
- ->Args({8<<10, 128})
- ->Args({1<<10, 512})
- ->Args({2<<10, 512})
- ->Args({4<<10, 512})
- ->Args({8<<10, 512});
-
-// The preceding code is quite repetitive, and can be replaced with
-// the following short-hand. The following macro will pick a few
-// appropriate arguments in the product of the two specified ranges
-// and will generate a microbenchmark for each such pair.
-BENCHMARK(BM_SetInsert)->Ranges({{1<<10, 8<<10}, {128, 512}});
-
-// For more complex patterns of inputs, passing a custom function
-// to Apply allows programmatic specification of an
-// arbitrary set of arguments to run the microbenchmark on.
-// The following example enumerates a dense range on
-// one parameter, and a sparse range on the second.
-static void CustomArguments(benchmark::Benchmark* b) {
- for (int i = 0; i <= 10; ++i)
- for (int j = 32; j <= 1024*1024; j *= 8)
- b->Args({i, j});
-}
-BENCHMARK(BM_SetInsert)->Apply(CustomArguments);
-
-// Templated microbenchmarks work the same way:
-// Produce then consume 'size' messages 'iters' times
-// Measures throughput in the absence of multiprogramming.
-template <class Q> int BM_Sequential(benchmark::State& state) {
- Q q;
- typename Q::value_type v;
- for (auto _ : state) {
- for (int i = state.range(0); i--; )
- q.push(v);
- for (int e = state.range(0); e--; )
- q.Wait(&v);
- }
- // actually messages, not bytes:
- state.SetBytesProcessed(state.iterations() * state.range(0));
-}
-BENCHMARK_TEMPLATE(BM_Sequential, WaitQueue<int>)->Range(1<<0, 1<<10);
-
-Use `Benchmark::MinTime(double t)` to set the minimum time used to run the
-benchmark. This option overrides the `benchmark_min_time` flag.
-
-void BM_test(benchmark::State& state) {
- ... body ...
-}
-BENCHMARK(BM_test)->MinTime(2.0); // Run for at least 2 seconds.
-
-In a multithreaded test, it is guaranteed that none of the threads will start
-until all have reached the loop start, and all will have finished before any
-thread exits the loop body. As such, any global setup or teardown you want to
-do can be wrapped in a check against the thread index:
-
-static void BM_MultiThreaded(benchmark::State& state) {
- if (state.thread_index() == 0) {
- // Setup code here.
- }
- for (auto _ : state) {
- // Run the test as normal.
- }
- if (state.thread_index() == 0) {
- // Teardown code here.
- }
-}
-BENCHMARK(BM_MultiThreaded)->Threads(4);
-
-
-If a benchmark runs a few milliseconds it may be hard to visually compare the
-measured times, since the output data is given in nanoseconds per default. In
-order to manually set the time unit, you can specify it manually:
-
-BENCHMARK(BM_test)->Unit(benchmark::kMillisecond);
-*/
-
#ifndef BENCHMARK_BENCHMARK_H_
#define BENCHMARK_BENCHMARK_H_
-#include <stdint.h>
-
-#include <algorithm>
-#include <atomic>
-#include <cassert>
-#include <cstddef>
-#include <functional>
-#include <iosfwd>
-#include <limits>
-#include <map>
-#include <memory>
-#include <set>
-#include <string>
-#include <type_traits>
-#include <utility>
-#include <vector>
-
-#include "benchmark/export.h"
-
-#if defined(_MSC_VER)
-#include <intrin.h> // for _ReadWriteBarrier
-#endif
-
-#define BENCHMARK_DISALLOW_COPY_AND_ASSIGN(TypeName) \
- TypeName(const TypeName&) = delete; \
- TypeName& operator=(const TypeName&) = delete
-
-#ifdef BENCHMARK_HAS_CXX17
-#define BENCHMARK_UNUSED [[maybe_unused]]
-#elif defined(__GNUC__) || defined(__clang__)
-#define BENCHMARK_UNUSED __attribute__((unused))
-#else
-#define BENCHMARK_UNUSED
-#endif
-
-// Used to annotate functions, methods and classes so they
-// are not optimized by the compiler. Useful for tests
-// where you expect loops to stay in place churning cycles
-#if defined(__clang__)
-#define BENCHMARK_DONT_OPTIMIZE __attribute__((optnone))
-#elif defined(__GNUC__) || defined(__GNUG__)
-#define BENCHMARK_DONT_OPTIMIZE __attribute__((optimize(0)))
-#else
-// MSVC & Intel do not have a no-optimize attribute, only line pragmas
-#define BENCHMARK_DONT_OPTIMIZE
-#endif
-
-#if defined(__GNUC__) || defined(__clang__)
-#define BENCHMARK_ALWAYS_INLINE __attribute__((always_inline))
-#elif defined(_MSC_VER) && !defined(__clang__)
-#define BENCHMARK_ALWAYS_INLINE __forceinline
-#define __func__ __FUNCTION__
-#else
-#define BENCHMARK_ALWAYS_INLINE
-#endif
-
-#define BENCHMARK_INTERNAL_TOSTRING2(x) #x
-#define BENCHMARK_INTERNAL_TOSTRING(x) BENCHMARK_INTERNAL_TOSTRING2(x)
-
-// clang-format off
-#if (defined(__GNUC__) && !defined(__NVCC__) && !defined(__NVCOMPILER)) || defined(__clang__)
-#define BENCHMARK_BUILTIN_EXPECT(x, y) __builtin_expect(x, y)
-#define BENCHMARK_DEPRECATED_MSG(msg) __attribute__((deprecated(msg)))
-#define BENCHMARK_DISABLE_DEPRECATED_WARNING \
- _Pragma("GCC diagnostic push") \
- _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
-#define BENCHMARK_RESTORE_DEPRECATED_WARNING _Pragma("GCC diagnostic pop")
-#elif defined(__NVCOMPILER)
-#define BENCHMARK_BUILTIN_EXPECT(x, y) __builtin_expect(x, y)
-#define BENCHMARK_DEPRECATED_MSG(msg) __attribute__((deprecated(msg)))
-#define BENCHMARK_DISABLE_DEPRECATED_WARNING \
- _Pragma("diagnostic push") \
- _Pragma("diag_suppress deprecated_entity_with_custom_message")
-#define BENCHMARK_RESTORE_DEPRECATED_WARNING _Pragma("diagnostic pop")
-#elif defined(_MSC_VER)
-#define BENCHMARK_BUILTIN_EXPECT(x, y) x
-#define BENCHMARK_DEPRECATED_MSG(msg) __declspec(deprecated(msg))
-#define BENCHMARK_WARNING_MSG(msg) \
- __pragma(message(__FILE__ "(" BENCHMARK_INTERNAL_TOSTRING( \
- __LINE__) ") : warning note: " msg))
-#define BENCHMARK_DISABLE_DEPRECATED_WARNING \
- __pragma(warning(push)) \
- __pragma(warning(disable : 4996))
-#define BENCHMARK_RESTORE_DEPRECATED_WARNING __pragma(warning(pop))
-#else
-#define BENCHMARK_BUILTIN_EXPECT(x, y) x
-#define BENCHMARK_DEPRECATED_MSG(msg)
-#define BENCHMARK_WARNING_MSG(msg) \
- __pragma(message(__FILE__ "(" BENCHMARK_INTERNAL_TOSTRING( \
- __LINE__) ") : warning note: " msg))
-#define BENCHMARK_DISABLE_DEPRECATED_WARNING
-#define BENCHMARK_RESTORE_DEPRECATED_WARNING
-#endif
-// clang-format on
-
-#if defined(__GNUC__) && !defined(__clang__)
-#define BENCHMARK_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
-#endif
-
-#ifndef __has_builtin
-#define __has_builtin(x) 0
-#endif
-
-#if defined(__GNUC__) || __has_builtin(__builtin_unreachable)
-#define BENCHMARK_UNREACHABLE() __builtin_unreachable()
-#elif defined(_MSC_VER)
-#define BENCHMARK_UNREACHABLE() __assume(false)
-#else
-#define BENCHMARK_UNREACHABLE() ((void)0)
-#endif
-
-#if defined(__GNUC__)
-// Determine the cacheline size based on architecture
-#if defined(__i386__) || defined(__x86_64__)
-#define BENCHMARK_INTERNAL_CACHELINE_SIZE 64
-#elif defined(__powerpc64__)
-#define BENCHMARK_INTERNAL_CACHELINE_SIZE 128
-#elif defined(__aarch64__)
-#define BENCHMARK_INTERNAL_CACHELINE_SIZE 64
-#elif defined(__arm__)
-// Cache line sizes for ARM: These values are not strictly correct since
-// cache line sizes depend on implementations, not architectures. There
-// are even implementations with cache line sizes configurable at boot
-// time.
-#if defined(__ARM_ARCH_5T__)
-#define BENCHMARK_INTERNAL_CACHELINE_SIZE 32
-#elif defined(__ARM_ARCH_7A__)
-#define BENCHMARK_INTERNAL_CACHELINE_SIZE 64
-#endif // ARM_ARCH
-#endif // arches
-#endif // __GNUC__
-
-#ifndef BENCHMARK_INTERNAL_CACHELINE_SIZE
-// A reasonable default guess. Note that overestimates tend to waste more
-// space, while underestimates tend to waste more time.
-#define BENCHMARK_INTERNAL_CACHELINE_SIZE 64
-#endif
-
-#if defined(__GNUC__)
-// Indicates that the declared object be cache aligned using
-// `BENCHMARK_INTERNAL_CACHELINE_SIZE` (see above).
-#define BENCHMARK_INTERNAL_CACHELINE_ALIGNED \
- __attribute__((aligned(BENCHMARK_INTERNAL_CACHELINE_SIZE)))
-#elif defined(_MSC_VER)
-#define BENCHMARK_INTERNAL_CACHELINE_ALIGNED \
- __declspec(align(BENCHMARK_INTERNAL_CACHELINE_SIZE))
-#else
-#define BENCHMARK_INTERNAL_CACHELINE_ALIGNED
-#endif
-
-#if defined(_MSC_VER)
-#pragma warning(push)
-// C4251: <symbol> needs to have dll-interface to be used by clients of class
-#pragma warning(disable : 4251)
-#endif // _MSC_VER_
-
-namespace benchmark {
-
-namespace internal {
-#if (__cplusplus < 201402L || (defined(_MSC_VER) && _MSVC_LANG < 201402L))
-template <typename T, typename... Args>
-std::unique_ptr<T> make_unique(Args&&... args) {
- return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
-}
-#else
-using ::std::make_unique;
-#endif
-} // namespace internal
-
-class BenchmarkReporter;
-class State;
-
-using IterationCount = int64_t;
-
-// Define alias of Setup/Teardown callback function type
-using callback_function = std::function<void(const benchmark::State&)>;
-
-// Default number of minimum benchmark running time in seconds.
-const char kDefaultMinTimeStr[] = "0.5s";
-
-BENCHMARK_EXPORT void MaybeReenterWithoutASLR(int, char**);
-
-// Returns the version of the library.
-BENCHMARK_EXPORT std::string GetBenchmarkVersion();
-
-BENCHMARK_EXPORT void PrintDefaultHelp();
-
-BENCHMARK_EXPORT void Initialize(int* argc, char** argv,
- void (*HelperPrintf)() = PrintDefaultHelp);
-BENCHMARK_EXPORT void Shutdown();
-
-// Report to stdout all arguments in 'argv' as unrecognized except the first.
-// Returns true there is at least on unrecognized argument (i.e. 'argc' > 1).
-BENCHMARK_EXPORT bool ReportUnrecognizedArguments(int argc, char** argv);
-
-// Returns the current value of --benchmark_filter.
-BENCHMARK_EXPORT std::string GetBenchmarkFilter();
-
-// Sets a new value to --benchmark_filter. (This will override this flag's
-// current value).
-// Should be called after `benchmark::Initialize()`, as
-// `benchmark::Initialize()` will override the flag's value.
-BENCHMARK_EXPORT void SetBenchmarkFilter(std::string value);
-
-// Returns the current value of --v (command line value for verbosity).
-BENCHMARK_EXPORT int32_t GetBenchmarkVerbosity();
-
-// Creates a default display reporter. Used by the library when no display
-// reporter is provided, but also made available for external use in case a
-// custom reporter should respect the `--benchmark_format` flag as a fallback
-BENCHMARK_EXPORT BenchmarkReporter* CreateDefaultDisplayReporter();
-
-// Generate a list of benchmarks matching the specified --benchmark_filter flag
-// and if --benchmark_list_tests is specified return after printing the name
-// of each matching benchmark. Otherwise run each matching benchmark and
-// report the results.
-//
-// spec : Specify the benchmarks to run. If users do not specify this arg,
-// then the value of FLAGS_benchmark_filter
-// will be used.
-//
-// The second and third overload use the specified 'display_reporter' and
-// 'file_reporter' respectively. 'file_reporter' will write to the file
-// specified
-// by '--benchmark_out'. If '--benchmark_out' is not given the
-// 'file_reporter' is ignored.
-//
-// RETURNS: The number of matching benchmarks.
-BENCHMARK_EXPORT size_t RunSpecifiedBenchmarks();
-BENCHMARK_EXPORT size_t RunSpecifiedBenchmarks(std::string spec);
-
-BENCHMARK_EXPORT size_t
-RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter);
-BENCHMARK_EXPORT size_t
-RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter, std::string spec);
-
-BENCHMARK_EXPORT size_t RunSpecifiedBenchmarks(
- BenchmarkReporter* display_reporter, BenchmarkReporter* file_reporter);
-BENCHMARK_EXPORT size_t
-RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter,
- BenchmarkReporter* file_reporter, std::string spec);
-
-// TimeUnit is passed to a benchmark in order to specify the order of magnitude
-// for the measured time.
-enum TimeUnit { kNanosecond, kMicrosecond, kMillisecond, kSecond };
-
-BENCHMARK_EXPORT TimeUnit GetDefaultTimeUnit();
-
-// Sets the default time unit the benchmarks use
-// Has to be called before the benchmark loop to take effect
-BENCHMARK_EXPORT void SetDefaultTimeUnit(TimeUnit unit);
-
-// If a MemoryManager is registered (via RegisterMemoryManager()),
-// it can be used to collect and report allocation metrics for a run of the
-// benchmark.
-class MemoryManager {
- public:
- static constexpr int64_t TombstoneValue = std::numeric_limits<int64_t>::max();
-
- struct Result {
- Result()
- : num_allocs(0),
- max_bytes_used(0),
- total_allocated_bytes(TombstoneValue),
- net_heap_growth(TombstoneValue),
- memory_iterations(0) {}
-
- // The number of allocations made in total between Start and Stop.
- int64_t num_allocs;
-
- // The peak memory use between Start and Stop.
- int64_t max_bytes_used;
-
- // The total memory allocated, in bytes, between Start and Stop.
- // Init'ed to TombstoneValue if metric not available.
- int64_t total_allocated_bytes;
-
- // The net changes in memory, in bytes, between Start and Stop.
- // ie., total_allocated_bytes - total_deallocated_bytes.
- // Init'ed to TombstoneValue if metric not available.
- int64_t net_heap_growth;
-
- IterationCount memory_iterations;
- };
-
- virtual ~MemoryManager() {}
-
- // Implement this to start recording allocation information.
- virtual void Start() = 0;
-
- // Implement this to stop recording and fill out the given Result structure.
- virtual void Stop(Result& result) = 0;
-};
-
-// Register a MemoryManager instance that will be used to collect and report
-// allocation measurements for benchmark runs.
-BENCHMARK_EXPORT
-void RegisterMemoryManager(MemoryManager* memory_manager);
-
-// If a ProfilerManager is registered (via RegisterProfilerManager()), the
-// benchmark will be run an additional time under the profiler to collect and
-// report profile metrics for the run of the benchmark.
-class ProfilerManager {
- public:
- virtual ~ProfilerManager() {}
-
- // This is called after `Setup()` code and right before the benchmark is run.
- virtual void AfterSetupStart() = 0;
-
- // This is called before `Teardown()` code and right after the benchmark
- // completes.
- virtual void BeforeTeardownStop() = 0;
-};
-
-// Register a ProfilerManager instance that will be used to collect and report
-// profile measurements for benchmark runs.
-BENCHMARK_EXPORT
-void RegisterProfilerManager(ProfilerManager* profiler_manager);
-
-// Add a key-value pair to output as part of the context stanza in the report.
-BENCHMARK_EXPORT
-void AddCustomContext(std::string key, std::string value);
-
-class Benchmark;
-
-namespace internal {
-class BenchmarkImp;
-class BenchmarkFamilies;
-
-BENCHMARK_EXPORT std::map<std::string, std::string>*& GetGlobalContext();
-
-BENCHMARK_EXPORT
-void UseCharPointer(char const volatile*);
-
-// Take ownership of the pointer and register the benchmark. Return the
-// registered benchmark.
-BENCHMARK_EXPORT Benchmark* RegisterBenchmarkInternal(
- std::unique_ptr<Benchmark>);
-
-// Ensure that the standard streams are properly initialized in every TU.
-BENCHMARK_EXPORT int InitializeStreams();
-BENCHMARK_UNUSED static int stream_init_anchor = InitializeStreams();
-
-} // namespace internal
-
-#if (!defined(__GNUC__) && !defined(__clang__)) || defined(__pnacl__) || \
- defined(__EMSCRIPTEN__)
-#define BENCHMARK_HAS_NO_INLINE_ASSEMBLY
-#endif
-
-// Force the compiler to flush pending writes to global memory. Acts as an
-// effective read/write barrier
-inline BENCHMARK_ALWAYS_INLINE void ClobberMemory() {
- std::atomic_signal_fence(std::memory_order_acq_rel);
-}
-
-// The DoNotOptimize(...) function can be used to prevent a value or
-// expression from being optimized away by the compiler. This function is
-// intended to add little to no overhead.
-// See: https://youtu.be/nXaxk27zwlk?t=2441
-#ifndef BENCHMARK_HAS_NO_INLINE_ASSEMBLY
-#if !defined(__GNUC__) || defined(__llvm__) || defined(__INTEL_COMPILER)
-template <class Tp>
-BENCHMARK_DEPRECATED_MSG(
- "The const-ref version of this method can permit "
- "undesired compiler optimizations in benchmarks")
-inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) {
- asm volatile("" : : "r,m"(value) : "memory");
-}
-
-template <class Tp>
-inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp& value) {
-#if defined(__clang__)
- asm volatile("" : "+r,m"(value) : : "memory");
-#else
- asm volatile("" : "+m,r"(value) : : "memory");
-#endif
-}
-
-template <class Tp>
-inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp&& value) {
-#if defined(__clang__)
- asm volatile("" : "+r,m"(value) : : "memory");
-#else
- asm volatile("" : "+m,r"(value) : : "memory");
-#endif
-}
-// !defined(__GNUC__) || defined(__llvm__) || defined(__INTEL_COMPILER)
-#elif (__GNUC__ >= 5)
-// Workaround for a bug with full argument copy overhead with GCC.
-// See: #1340 and https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105519
-template <class Tp>
-BENCHMARK_DEPRECATED_MSG(
- "The const-ref version of this method can permit "
- "undesired compiler optimizations in benchmarks")
-inline BENCHMARK_ALWAYS_INLINE
- typename std::enable_if<std::is_trivially_copyable<Tp>::value &&
- (sizeof(Tp) <= sizeof(Tp*))>::type
- DoNotOptimize(Tp const& value) {
- asm volatile("" : : "r,m"(value) : "memory");
-}
-
-template <class Tp>
-BENCHMARK_DEPRECATED_MSG(
- "The const-ref version of this method can permit "
- "undesired compiler optimizations in benchmarks")
-inline BENCHMARK_ALWAYS_INLINE
- typename std::enable_if<!std::is_trivially_copyable<Tp>::value ||
- (sizeof(Tp) > sizeof(Tp*))>::type
- DoNotOptimize(Tp const& value) {
- asm volatile("" : : "m"(value) : "memory");
-}
-
-template <class Tp>
-inline BENCHMARK_ALWAYS_INLINE
- typename std::enable_if<std::is_trivially_copyable<Tp>::value &&
- (sizeof(Tp) <= sizeof(Tp*))>::type
- DoNotOptimize(Tp& value) {
- asm volatile("" : "+m,r"(value) : : "memory");
-}
-
-template <class Tp>
-inline BENCHMARK_ALWAYS_INLINE
- typename std::enable_if<!std::is_trivially_copyable<Tp>::value ||
- (sizeof(Tp) > sizeof(Tp*))>::type
- DoNotOptimize(Tp& value) {
- asm volatile("" : "+m"(value) : : "memory");
-}
-
-template <class Tp>
-inline BENCHMARK_ALWAYS_INLINE
- typename std::enable_if<std::is_trivially_copyable<Tp>::value &&
- (sizeof(Tp) <= sizeof(Tp*))>::type
- DoNotOptimize(Tp&& value) {
- asm volatile("" : "+m,r"(value) : : "memory");
-}
-
-template <class Tp>
-inline BENCHMARK_ALWAYS_INLINE
- typename std::enable_if<!std::is_trivially_copyable<Tp>::value ||
- (sizeof(Tp) > sizeof(Tp*))>::type
- DoNotOptimize(Tp&& value) {
- asm volatile("" : "+m"(value) : : "memory");
-}
-// !defined(__GNUC__) || defined(__llvm__) || defined(__INTEL_COMPILER)
-#endif
-
-#elif defined(_MSC_VER)
-template <class Tp>
-BENCHMARK_DEPRECATED_MSG(
- "The const-ref version of this method can permit "
- "undesired compiler optimizations in benchmarks")
-inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) {
- internal::UseCharPointer(&reinterpret_cast<char const volatile&>(value));
- _ReadWriteBarrier();
-}
-
-template <class Tp>
-inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp& value) {
- internal::UseCharPointer(&reinterpret_cast<char const volatile&>(value));
- _ReadWriteBarrier();
-}
-
-template <class Tp>
-inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp&& value) {
- internal::UseCharPointer(&reinterpret_cast<char const volatile&>(value));
- _ReadWriteBarrier();
-}
-#else
-template <class Tp>
-inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp&& value) {
- internal::UseCharPointer(&reinterpret_cast<char const volatile&>(value));
-}
-// FIXME Add ClobberMemory() for non-gnu and non-msvc compilers, before C++11.
-#endif
-
-// This class is used for user-defined counters.
-class Counter {
- public:
- enum Flags {
- kDefaults = 0,
- // Mark the counter as a rate. It will be presented divided
- // by the duration of the benchmark.
- kIsRate = 1 << 0,
- // Mark the counter as a thread-average quantity. It will be
- // presented divided by the number of threads.
- kAvgThreads = 1 << 1,
- // Mark the counter as a thread-average rate. See above.
- kAvgThreadsRate = kIsRate | kAvgThreads,
- // Mark the counter as a constant value, valid/same for *every* iteration.
- // When reporting, it will be *multiplied* by the iteration count.
- kIsIterationInvariant = 1 << 2,
- // Mark the counter as a constant rate.
- // When reporting, it will be *multiplied* by the iteration count
- // and then divided by the duration of the benchmark.
- kIsIterationInvariantRate = kIsRate | kIsIterationInvariant,
- // Mark the counter as a iteration-average quantity.
- // It will be presented divided by the number of iterations.
- kAvgIterations = 1 << 3,
- // Mark the counter as a iteration-average rate. See above.
- kAvgIterationsRate = kIsRate | kAvgIterations,
-
- // In the end, invert the result. This is always done last!
- kInvert = 1 << 31
- };
-
- enum OneK {
- // 1'000 items per 1k
- kIs1000 = 1000,
- // 1'024 items per 1k
- kIs1024 = 1024
- };
-
- double value;
- Flags flags;
- OneK oneK;
-
- BENCHMARK_ALWAYS_INLINE
- Counter(double v = 0., Flags f = kDefaults, OneK k = kIs1000)
- : value(v), flags(f), oneK(k) {}
-
- BENCHMARK_ALWAYS_INLINE operator double const&() const { return value; }
- BENCHMARK_ALWAYS_INLINE operator double&() { return value; }
-};
-
-// A helper for user code to create unforeseen combinations of Flags, without
-// having to do this cast manually each time, or providing this operator.
-Counter::Flags inline operator|(const Counter::Flags& LHS,
- const Counter::Flags& RHS) {
- return static_cast<Counter::Flags>(static_cast<int>(LHS) |
- static_cast<int>(RHS));
-}
-
-// This is the container for the user-defined counters.
-typedef std::map<std::string, Counter> UserCounters;
-
-// BigO is passed to a benchmark in order to specify the asymptotic
-// computational
-// complexity for the benchmark. In case oAuto is selected, complexity will be
-// calculated automatically to the best fit.
-enum BigO { oNone, o1, oN, oNSquared, oNCubed, oLogN, oNLogN, oAuto, oLambda };
-
-typedef int64_t ComplexityN;
-
-enum StatisticUnit { kTime, kPercentage };
-
-// BigOFunc is passed to a benchmark in order to specify the asymptotic
-// computational complexity for the benchmark.
-typedef double(BigOFunc)(ComplexityN);
-
-// StatisticsFunc is passed to a benchmark in order to compute some descriptive
-// statistics over all the measurements of some type
-typedef double(StatisticsFunc)(const std::vector<double>&);
-
-namespace internal {
-struct Statistics {
- std::string name_;
- StatisticsFunc* compute_;
- StatisticUnit unit_;
-
- Statistics(const std::string& name, StatisticsFunc* compute,
- StatisticUnit unit = kTime)
- : name_(name), compute_(compute), unit_(unit) {}
-};
-
-class BenchmarkInstance;
-class ThreadTimer;
-class ThreadManager;
-class PerfCountersMeasurement;
-
-enum AggregationReportMode : unsigned {
- // The mode has not been manually specified
- ARM_Unspecified = 0,
- // The mode is user-specified.
- // This may or may not be set when the following bit-flags are set.
- ARM_Default = 1U << 0U,
- // File reporter should only output aggregates.
- ARM_FileReportAggregatesOnly = 1U << 1U,
- // Display reporter should only output aggregates
- ARM_DisplayReportAggregatesOnly = 1U << 2U,
- // Both reporters should only display aggregates.
- ARM_ReportAggregatesOnly =
- ARM_FileReportAggregatesOnly | ARM_DisplayReportAggregatesOnly
-};
-
-enum Skipped : unsigned {
- NotSkipped = 0,
- SkippedWithMessage,
- SkippedWithError
-};
-
-} // namespace internal
-
-#if defined(_MSC_VER)
-#pragma warning(push)
-// C4324: 'benchmark::State': structure was padded due to alignment specifier
-#pragma warning(disable : 4324)
-#endif // _MSC_VER_
-// State is passed to a running Benchmark and contains state for the
-// benchmark to use.
-class BENCHMARK_EXPORT BENCHMARK_INTERNAL_CACHELINE_ALIGNED State {
- public:
- struct StateIterator;
- friend struct StateIterator;
-
- // Returns iterators used to run each iteration of a benchmark using a
- // C++11 ranged-based for loop. These functions should not be called directly.
- //
- // REQUIRES: The benchmark has not started running yet. Neither begin nor end
- // have been called previously.
- //
- // NOTE: KeepRunning may not be used after calling either of these functions.
- inline BENCHMARK_ALWAYS_INLINE StateIterator begin();
- inline BENCHMARK_ALWAYS_INLINE StateIterator end();
-
- // Returns true if the benchmark should continue through another iteration.
- // NOTE: A benchmark may not return from the test until KeepRunning() has
- // returned false.
- inline bool KeepRunning();
-
- // Returns true iff the benchmark should run n more iterations.
- // REQUIRES: 'n' > 0.
- // NOTE: A benchmark must not return from the test until KeepRunningBatch()
- // has returned false.
- // NOTE: KeepRunningBatch() may overshoot by up to 'n' iterations.
- //
- // Intended usage:
- // while (state.KeepRunningBatch(1000)) {
- // // process 1000 elements
- // }
- inline bool KeepRunningBatch(IterationCount n);
-
- // REQUIRES: timer is running and 'SkipWithMessage(...)' or
- // 'SkipWithError(...)' has not been called by the current thread.
- // Stop the benchmark timer. If not called, the timer will be
- // automatically stopped after the last iteration of the benchmark loop.
- //
- // For threaded benchmarks the PauseTiming() function only pauses the timing
- // for the current thread.
- //
- // NOTE: The "real time" measurement is per-thread. If different threads
- // report different measurements the largest one is reported.
- //
- // NOTE: PauseTiming()/ResumeTiming() are relatively
- // heavyweight, and so their use should generally be avoided
- // within each benchmark iteration, if possible.
- void PauseTiming();
-
- // REQUIRES: timer is not running and 'SkipWithMessage(...)' or
- // 'SkipWithError(...)' has not been called by the current thread.
- // Start the benchmark timer. The timer is NOT running on entrance to the
- // benchmark function. It begins running after control flow enters the
- // benchmark loop.
- //
- // NOTE: PauseTiming()/ResumeTiming() are relatively
- // heavyweight, and so their use should generally be avoided
- // within each benchmark iteration, if possible.
- void ResumeTiming();
-
- // REQUIRES: 'SkipWithMessage(...)' or 'SkipWithError(...)' has not been
- // called previously by the current thread.
- // Report the benchmark as resulting in being skipped with the specified
- // 'msg'.
- // After this call the user may explicitly 'return' from the benchmark.
- //
- // If the ranged-for style of benchmark loop is used, the user must explicitly
- // break from the loop, otherwise all future iterations will be run.
- // If the 'KeepRunning()' loop is used the current thread will automatically
- // exit the loop at the end of the current iteration.
- //
- // For threaded benchmarks only the current thread stops executing and future
- // calls to `KeepRunning()` will block until all threads have completed
- // the `KeepRunning()` loop. If multiple threads report being skipped only the
- // first skip message is used.
- //
- // NOTE: Calling 'SkipWithMessage(...)' does not cause the benchmark to exit
- // the current scope immediately. If the function is called from within
- // the 'KeepRunning()' loop the current iteration will finish. It is the users
- // responsibility to exit the scope as needed.
- void SkipWithMessage(const std::string& msg);
-
- // REQUIRES: 'SkipWithMessage(...)' or 'SkipWithError(...)' has not been
- // called previously by the current thread.
- // Report the benchmark as resulting in an error with the specified 'msg'.
- // After this call the user may explicitly 'return' from the benchmark.
- //
- // If the ranged-for style of benchmark loop is used, the user must explicitly
- // break from the loop, otherwise all future iterations will be run.
- // If the 'KeepRunning()' loop is used the current thread will automatically
- // exit the loop at the end of the current iteration.
- //
- // For threaded benchmarks only the current thread stops executing and future
- // calls to `KeepRunning()` will block until all threads have completed
- // the `KeepRunning()` loop. If multiple threads report an error only the
- // first error message is used.
- //
- // NOTE: Calling 'SkipWithError(...)' does not cause the benchmark to exit
- // the current scope immediately. If the function is called from within
- // the 'KeepRunning()' loop the current iteration will finish. It is the users
- // responsibility to exit the scope as needed.
- void SkipWithError(const std::string& msg);
-
- // Returns true if 'SkipWithMessage(...)' or 'SkipWithError(...)' was called.
- bool skipped() const { return internal::NotSkipped != skipped_; }
-
- // Returns true if an error has been reported with 'SkipWithError(...)'.
- bool error_occurred() const { return internal::SkippedWithError == skipped_; }
-
- // REQUIRES: called exactly once per iteration of the benchmarking loop.
- // Set the manually measured time for this benchmark iteration, which
- // is used instead of automatically measured time if UseManualTime() was
- // specified.
- //
- // For threaded benchmarks the final value will be set to the largest
- // reported values.
- void SetIterationTime(double seconds);
-
- // Set the number of bytes processed by the current benchmark
- // execution. This routine is typically called once at the end of a
- // throughput oriented benchmark.
- //
- // REQUIRES: a benchmark has exited its benchmarking loop.
- BENCHMARK_ALWAYS_INLINE
- void SetBytesProcessed(int64_t bytes) {
- counters["bytes_per_second"] =
- Counter(static_cast<double>(bytes), Counter::kIsRate, Counter::kIs1024);
- }
-
- BENCHMARK_ALWAYS_INLINE
- int64_t bytes_processed() const {
- if (counters.find("bytes_per_second") != counters.end())
- return static_cast<int64_t>(counters.at("bytes_per_second"));
- return 0;
- }
-
- // If this routine is called with complexity_n > 0 and complexity report is
- // requested for the
- // family benchmark, then current benchmark will be part of the computation
- // and complexity_n will
- // represent the length of N.
- BENCHMARK_ALWAYS_INLINE
- void SetComplexityN(ComplexityN complexity_n) {
- complexity_n_ = complexity_n;
- }
-
- BENCHMARK_ALWAYS_INLINE
- ComplexityN complexity_length_n() const { return complexity_n_; }
-
- // If this routine is called with items > 0, then an items/s
- // label is printed on the benchmark report line for the currently
- // executing benchmark. It is typically called at the end of a processing
- // benchmark where a processing items/second output is desired.
- //
- // REQUIRES: a benchmark has exited its benchmarking loop.
- BENCHMARK_ALWAYS_INLINE
- void SetItemsProcessed(int64_t items) {
- counters["items_per_second"] =
- Counter(static_cast<double>(items), benchmark::Counter::kIsRate);
- }
-
- BENCHMARK_ALWAYS_INLINE
- int64_t items_processed() const {
- if (counters.find("items_per_second") != counters.end())
- return static_cast<int64_t>(counters.at("items_per_second"));
- return 0;
- }
-
- // If this routine is called, the specified label is printed at the
- // end of the benchmark report line for the currently executing
- // benchmark. Example:
- // static void BM_Compress(benchmark::State& state) {
- // ...
- // double compress = input_size / output_size;
- // state.SetLabel(StrFormat("compress:%.1f%%", 100.0*compression));
- // }
- // Produces output that looks like:
- // BM_Compress 50 50 14115038 compress:27.3%
- //
- // REQUIRES: a benchmark has exited its benchmarking loop.
- void SetLabel(const std::string& label);
-
- // Range arguments for this run. CHECKs if the argument has been set.
- BENCHMARK_ALWAYS_INLINE
- int64_t range(std::size_t pos = 0) const {
- assert(range_.size() > pos);
- return range_[pos];
- }
-
- BENCHMARK_DEPRECATED_MSG("use 'range(0)' instead")
- int64_t range_x() const { return range(0); }
-
- BENCHMARK_DEPRECATED_MSG("use 'range(1)' instead")
- int64_t range_y() const { return range(1); }
-
- // Number of threads concurrently executing the benchmark.
- BENCHMARK_ALWAYS_INLINE
- int threads() const { return threads_; }
-
- // Index of the executing thread. Values from [0, threads).
- BENCHMARK_ALWAYS_INLINE
- int thread_index() const { return thread_index_; }
-
- BENCHMARK_ALWAYS_INLINE
- IterationCount iterations() const {
- if (BENCHMARK_BUILTIN_EXPECT(!started_, false)) {
- return 0;
- }
- return max_iterations - total_iterations_ + batch_leftover_;
- }
-
- BENCHMARK_ALWAYS_INLINE
- std::string name() const { return name_; }
-
- size_t range_size() const { return range_.size(); }
-
- private:
- // items we expect on the first cache line (ie 64 bytes of the struct)
- // When total_iterations_ is 0, KeepRunning() and friends will return false.
- // May be larger than max_iterations.
- IterationCount total_iterations_;
-
- // When using KeepRunningBatch(), batch_leftover_ holds the number of
- // iterations beyond max_iters that were run. Used to track
- // completed_iterations_ accurately.
- IterationCount batch_leftover_;
-
- public:
- const IterationCount max_iterations;
-
- private:
- bool started_;
- bool finished_;
- internal::Skipped skipped_;
-
- // items we don't need on the first cache line
- std::vector<int64_t> range_;
-
- ComplexityN complexity_n_;
-
- public:
- // Container for user-defined counters.
- UserCounters counters;
-
- private:
- State(std::string name, IterationCount max_iters,
- const std::vector<int64_t>& ranges, int thread_i, int n_threads,
- internal::ThreadTimer* timer, internal::ThreadManager* manager,
- internal::PerfCountersMeasurement* perf_counters_measurement,
- ProfilerManager* profiler_manager);
-
- void StartKeepRunning();
- // Implementation of KeepRunning() and KeepRunningBatch().
- // is_batch must be true unless n is 1.
- inline bool KeepRunningInternal(IterationCount n, bool is_batch);
- void FinishKeepRunning();
-
- const std::string name_;
- const int thread_index_;
- const int threads_;
-
- internal::ThreadTimer* const timer_;
- internal::ThreadManager* const manager_;
- internal::PerfCountersMeasurement* const perf_counters_measurement_;
- ProfilerManager* const profiler_manager_;
-
- friend class internal::BenchmarkInstance;
-};
-#if defined(_MSC_VER)
-#pragma warning(pop)
-#endif // _MSC_VER_
-
-inline BENCHMARK_ALWAYS_INLINE bool State::KeepRunning() {
- return KeepRunningInternal(1, /*is_batch=*/false);
-}
-
-inline BENCHMARK_ALWAYS_INLINE bool State::KeepRunningBatch(IterationCount n) {
- return KeepRunningInternal(n, /*is_batch=*/true);
-}
-
-inline BENCHMARK_ALWAYS_INLINE bool State::KeepRunningInternal(IterationCount n,
- bool is_batch) {
- // total_iterations_ is set to 0 by the constructor, and always set to a
- // nonzero value by StartKepRunning().
- assert(n > 0);
- // n must be 1 unless is_batch is true.
- assert(is_batch || n == 1);
- if (BENCHMARK_BUILTIN_EXPECT(total_iterations_ >= n, true)) {
- total_iterations_ -= n;
- return true;
- }
- if (!started_) {
- StartKeepRunning();
- if (!skipped() && total_iterations_ >= n) {
- total_iterations_ -= n;
- return true;
- }
- }
- // For non-batch runs, total_iterations_ must be 0 by now.
- if (is_batch && total_iterations_ != 0) {
- batch_leftover_ = n - total_iterations_;
- total_iterations_ = 0;
- return true;
- }
- FinishKeepRunning();
- return false;
-}
-
-struct State::StateIterator {
- struct BENCHMARK_UNUSED Value {};
- typedef std::forward_iterator_tag iterator_category;
- typedef Value value_type;
- typedef Value reference;
- typedef Value pointer;
- typedef std::ptrdiff_t difference_type;
-
- private:
- friend class State;
- BENCHMARK_ALWAYS_INLINE
- StateIterator() : cached_(0), parent_() {}
-
- BENCHMARK_ALWAYS_INLINE
- explicit StateIterator(State* st)
- : cached_(st->skipped() ? 0 : st->max_iterations), parent_(st) {}
-
- public:
- BENCHMARK_ALWAYS_INLINE
- Value operator*() const { return Value(); }
-
- BENCHMARK_ALWAYS_INLINE
- StateIterator& operator++() {
- assert(cached_ > 0);
- --cached_;
- return *this;
- }
-
- BENCHMARK_ALWAYS_INLINE
- bool operator!=(StateIterator const&) const {
- if (BENCHMARK_BUILTIN_EXPECT(cached_ != 0, true)) return true;
- parent_->FinishKeepRunning();
- return false;
- }
-
- private:
- IterationCount cached_;
- State* const parent_;
-};
-
-inline BENCHMARK_ALWAYS_INLINE State::StateIterator State::begin() {
- return StateIterator(this);
-}
-inline BENCHMARK_ALWAYS_INLINE State::StateIterator State::end() {
- StartKeepRunning();
- return StateIterator();
-}
-
-// Base class for user-defined multi-threading
-struct ThreadRunnerBase {
- virtual ~ThreadRunnerBase() {}
- virtual void RunThreads(const std::function<void(int)>& fn) = 0;
-};
-
-// Define alias of ThreadRunner factory function type
-using threadrunner_factory =
- std::function<std::unique_ptr<ThreadRunnerBase>(int)>;
-
-// ------------------------------------------------------
-// Benchmark registration object. The BENCHMARK() macro expands into a
-// Benchmark* object. Various methods can be called on this object to
-// change the properties of the benchmark. Each method returns "this" so
-// that multiple method calls can chained into one expression.
-class BENCHMARK_EXPORT Benchmark {
- public:
- virtual ~Benchmark();
-
- // Note: the following methods all return "this" so that multiple
- // method calls can be chained together in one expression.
-
- // Specify the name of the benchmark
- Benchmark* Name(const std::string& name);
-
- // Run this benchmark once with "x" as the extra argument passed
- // to the function.
- // REQUIRES: The function passed to the constructor must accept an arg1.
- Benchmark* Arg(int64_t x);
-
- // Run this benchmark with the given time unit for the generated output report
- Benchmark* Unit(TimeUnit unit);
-
- // Run this benchmark once for a number of values picked from the
- // range [start..limit]. (start and limit are always picked.)
- // REQUIRES: The function passed to the constructor must accept an arg1.
- Benchmark* Range(int64_t start, int64_t limit);
-
- // Run this benchmark once for all values in the range [start..limit] with
- // specific step
- // REQUIRES: The function passed to the constructor must accept an arg1.
- Benchmark* DenseRange(int64_t start, int64_t limit, int step = 1);
-
- // Run this benchmark once with "args" as the extra arguments passed
- // to the function.
- // REQUIRES: The function passed to the constructor must accept arg1, arg2 ...
- Benchmark* Args(const std::vector<int64_t>& args);
-
- // Equivalent to Args({x, y})
- // NOTE: This is a legacy C++03 interface provided for compatibility only.
- // New code should use 'Args'.
- Benchmark* ArgPair(int64_t x, int64_t y) {
- std::vector<int64_t> args;
- args.push_back(x);
- args.push_back(y);
- return Args(args);
- }
-
- // Run this benchmark once for a number of values picked from the
- // ranges [start..limit]. (starts and limits are always picked.)
- // REQUIRES: The function passed to the constructor must accept arg1, arg2 ...
- Benchmark* Ranges(const std::vector<std::pair<int64_t, int64_t>>& ranges);
-
- // Run this benchmark once for each combination of values in the (cartesian)
- // product of the supplied argument lists.
- // REQUIRES: The function passed to the constructor must accept arg1, arg2 ...
- Benchmark* ArgsProduct(const std::vector<std::vector<int64_t>>& arglists);
-
- // Equivalent to ArgNames({name})
- Benchmark* ArgName(const std::string& name);
-
- // Set the argument names to display in the benchmark name. If not called,
- // only argument values will be shown.
- Benchmark* ArgNames(const std::vector<std::string>& names);
-
- // Equivalent to Ranges({{lo1, hi1}, {lo2, hi2}}).
- // NOTE: This is a legacy C++03 interface provided for compatibility only.
- // New code should use 'Ranges'.
- Benchmark* RangePair(int64_t lo1, int64_t hi1, int64_t lo2, int64_t hi2) {
- std::vector<std::pair<int64_t, int64_t>> ranges;
- ranges.push_back(std::make_pair(lo1, hi1));
- ranges.push_back(std::make_pair(lo2, hi2));
- return Ranges(ranges);
- }
-
- // Have "setup" and/or "teardown" invoked once for every benchmark run.
- // If the benchmark is multi-threaded (will run in k threads concurrently),
- // the setup callback will be be invoked exactly once (not k times) before
- // each run with k threads. Time allowing (e.g. for a short benchmark), there
- // may be multiple such runs per benchmark, each run with its own
- // "setup"/"teardown".
- //
- // If the benchmark uses different size groups of threads (e.g. via
- // ThreadRange), the above will be true for each size group.
- //
- // The callback will be passed a State object, which includes the number
- // of threads, thread-index, benchmark arguments, etc.
- Benchmark* Setup(callback_function&&);
- Benchmark* Setup(const callback_function&);
- Benchmark* Teardown(callback_function&&);
- Benchmark* Teardown(const callback_function&);
-
- // Pass this benchmark object to *func, which can customize
- // the benchmark by calling various methods like Arg, Args,
- // Threads, etc.
- Benchmark* Apply(const std::function<void(Benchmark* benchmark)>&);
-
- // Set the range multiplier for non-dense range. If not called, the range
- // multiplier kRangeMultiplier will be used.
- Benchmark* RangeMultiplier(int multiplier);
-
- // Set the minimum amount of time to use when running this benchmark. This
- // option overrides the `benchmark_min_time` flag.
- // REQUIRES: `t > 0` and `Iterations` has not been called on this benchmark.
- Benchmark* MinTime(double t);
-
- // Set the minimum amount of time to run the benchmark before taking runtimes
- // of this benchmark into account. This
- // option overrides the `benchmark_min_warmup_time` flag.
- // REQUIRES: `t >= 0` and `Iterations` has not been called on this benchmark.
- Benchmark* MinWarmUpTime(double t);
-
- // Specify the amount of iterations that should be run by this benchmark.
- // This option overrides the `benchmark_min_time` flag.
- // REQUIRES: 'n > 0' and `MinTime` has not been called on this benchmark.
- //
- // NOTE: This function should only be used when *exact* iteration control is
- // needed and never to control or limit how long a benchmark runs, where
- // `--benchmark_min_time=<N>s` or `MinTime(...)` should be used instead.
- Benchmark* Iterations(IterationCount n);
-
- // Specify the amount of times to repeat this benchmark. This option overrides
- // the `benchmark_repetitions` flag.
- // REQUIRES: `n > 0`
- Benchmark* Repetitions(int n);
-
- // Specify if each repetition of the benchmark should be reported separately
- // or if only the final statistics should be reported. If the benchmark
- // is not repeated then the single result is always reported.
- // Applies to *ALL* reporters (display and file).
- Benchmark* ReportAggregatesOnly(bool value = true);
-
- // Same as ReportAggregatesOnly(), but applies to display reporter only.
- Benchmark* DisplayAggregatesOnly(bool value = true);
-
- // By default, the CPU time is measured only for the main thread, which may
- // be unrepresentative if the benchmark uses threads internally. If called,
- // the total CPU time spent by all the threads will be measured instead.
- // By default, only the main thread CPU time will be measured.
- Benchmark* MeasureProcessCPUTime();
-
- // If a particular benchmark should use the Wall clock instead of the CPU time
- // (be it either the CPU time of the main thread only (default), or the
- // total CPU usage of the benchmark), call this method. If called, the elapsed
- // (wall) time will be used to control how many iterations are run, and in the
- // printing of items/second or MB/seconds values.
- // If not called, the CPU time used by the benchmark will be used.
- Benchmark* UseRealTime();
-
- // If a benchmark must measure time manually (e.g. if GPU execution time is
- // being
- // measured), call this method. If called, each benchmark iteration should
- // call
- // SetIterationTime(seconds) to report the measured time, which will be used
- // to control how many iterations are run, and in the printing of items/second
- // or MB/second values.
- Benchmark* UseManualTime();
-
- // Set the asymptotic computational complexity for the benchmark. If called
- // the asymptotic computational complexity will be shown on the output.
- Benchmark* Complexity(BigO complexity = benchmark::oAuto);
-
- // Set the asymptotic computational complexity for the benchmark. If called
- // the asymptotic computational complexity will be shown on the output.
- Benchmark* Complexity(BigOFunc* complexity);
-
- // Add this statistics to be computed over all the values of benchmark run
- Benchmark* ComputeStatistics(const std::string& name,
- StatisticsFunc* statistics,
- StatisticUnit unit = kTime);
-
- // Support for running multiple copies of the same benchmark concurrently
- // in multiple threads. This may be useful when measuring the scaling
- // of some piece of code.
-
- // Run one instance of this benchmark concurrently in t threads.
- Benchmark* Threads(int t);
-
- // Pick a set of values T from [min_threads,max_threads].
- // min_threads and max_threads are always included in T. Run this
- // benchmark once for each value in T. The benchmark run for a
- // particular value t consists of t threads running the benchmark
- // function concurrently. For example, consider:
- // BENCHMARK(Foo)->ThreadRange(1,16);
- // This will run the following benchmarks:
- // Foo in 1 thread
- // Foo in 2 threads
- // Foo in 4 threads
- // Foo in 8 threads
- // Foo in 16 threads
- Benchmark* ThreadRange(int min_threads, int max_threads);
-
- // For each value n in the range, run this benchmark once using n threads.
- // min_threads and max_threads are always included in the range.
- // stride specifies the increment. E.g. DenseThreadRange(1, 8, 3) starts
- // a benchmark with 1, 4, 7 and 8 threads.
- Benchmark* DenseThreadRange(int min_threads, int max_threads, int stride = 1);
-
- // Equivalent to ThreadRange(NumCPUs(), NumCPUs())
- Benchmark* ThreadPerCpu();
-
- // Sets a user-defined threadrunner (see ThreadRunnerBase)
- Benchmark* ThreadRunner(threadrunner_factory&& factory);
-
- virtual void Run(State& state) = 0;
-
- TimeUnit GetTimeUnit() const;
-
- protected:
- explicit Benchmark(const std::string& name);
- void SetName(const std::string& name);
-
- public:
- const char* GetName() const;
- int ArgsCnt() const;
- const char* GetArgName(int arg) const;
-
- private:
- friend class internal::BenchmarkFamilies;
- friend class internal::BenchmarkInstance;
-
- std::string name_;
- internal::AggregationReportMode aggregation_report_mode_;
- std::vector<std::string> arg_names_; // Args for all benchmark runs
- std::vector<std::vector<int64_t>> args_; // Args for all benchmark runs
-
- TimeUnit time_unit_;
- bool use_default_time_unit_;
-
- int range_multiplier_;
- double min_time_;
- double min_warmup_time_;
- IterationCount iterations_;
- int repetitions_;
- bool measure_process_cpu_time_;
- bool use_real_time_;
- bool use_manual_time_;
- BigO complexity_;
- BigOFunc* complexity_lambda_;
- std::vector<internal::Statistics> statistics_;
- std::vector<int> thread_counts_;
-
- callback_function setup_;
- callback_function teardown_;
-
- threadrunner_factory threadrunner_;
-
- BENCHMARK_DISALLOW_COPY_AND_ASSIGN(Benchmark);
-};
-
-namespace internal {
-
-// clang-format off
-typedef BENCHMARK_DEPRECATED_MSG("Use ::benchmark::Benchmark instead")
- ::benchmark::Benchmark Benchmark;
-typedef BENCHMARK_DEPRECATED_MSG(
- "Use ::benchmark::threadrunner_factory instead")
- ::benchmark::threadrunner_factory threadrunner_factory;
-// clang-format on
-
-typedef void(Function)(State&);
-
-} // namespace internal
-
-// Create and register a benchmark with the specified 'name' that invokes
-// the specified functor 'fn'.
-//
-// RETURNS: A pointer to the registered benchmark.
-Benchmark* RegisterBenchmark(const std::string& name, internal::Function* fn);
-
-template <class Lambda>
-Benchmark* RegisterBenchmark(const std::string& name, Lambda&& fn);
-
-// Remove all registered benchmarks. All pointers to previously registered
-// benchmarks are invalidated.
-BENCHMARK_EXPORT void ClearRegisteredBenchmarks();
-
-namespace internal {
-// The class used to hold all Benchmarks created from static function.
-// (ie those created using the BENCHMARK(...) macros.
-class BENCHMARK_EXPORT FunctionBenchmark : public benchmark::Benchmark {
- public:
- FunctionBenchmark(const std::string& name, Function* func)
- : Benchmark(name), func_(func) {}
-
- void Run(State& st) override;
-
- private:
- Function* func_;
-};
-
-template <class Lambda>
-class LambdaBenchmark : public benchmark::Benchmark {
- public:
- void Run(State& st) override { lambda_(st); }
-
- template <class OLambda>
- LambdaBenchmark(const std::string& name, OLambda&& lam)
- : Benchmark(name), lambda_(std::forward<OLambda>(lam)) {}
-
- private:
- LambdaBenchmark(LambdaBenchmark const&) = delete;
- Lambda lambda_;
-};
-} // namespace internal
-
-inline Benchmark* RegisterBenchmark(const std::string& name,
- internal::Function* fn) {
- return internal::RegisterBenchmarkInternal(
- ::benchmark::internal::make_unique<internal::FunctionBenchmark>(name,
- fn));
-}
-
-template <class Lambda>
-Benchmark* RegisterBenchmark(const std::string& name, Lambda&& fn) {
- using BenchType =
- internal::LambdaBenchmark<typename std::decay<Lambda>::type>;
- return internal::RegisterBenchmarkInternal(
- ::benchmark::internal::make_unique<BenchType>(name,
- std::forward<Lambda>(fn)));
-}
-
-template <class Lambda, class... Args>
-Benchmark* RegisterBenchmark(const std::string& name, Lambda&& fn,
- Args&&... args) {
- return benchmark::RegisterBenchmark(
- name, [=](benchmark::State& st) { fn(st, args...); });
-}
-
-// The base class for all fixture tests.
-class Fixture : public Benchmark {
- public:
- Fixture() : Benchmark("") {}
-
- void Run(State& st) override {
- this->SetUp(st);
- this->BenchmarkCase(st);
- this->TearDown(st);
- }
-
- // These will be deprecated ...
- virtual void SetUp(const State&) {}
- virtual void TearDown(const State&) {}
- // ... In favor of these.
- virtual void SetUp(State& st) { SetUp(const_cast<const State&>(st)); }
- virtual void TearDown(State& st) { TearDown(const_cast<const State&>(st)); }
-
- protected:
- virtual void BenchmarkCase(State&) = 0;
-};
-} // namespace benchmark
-
-// ------------------------------------------------------
-// Macro to register benchmarks
-
-// clang-format off
-#if defined(__clang__)
-#define BENCHMARK_DISABLE_COUNTER_WARNING \
- _Pragma("GCC diagnostic push") \
- _Pragma("GCC diagnostic ignored \"-Wunknown-warning-option\"") \
- _Pragma("GCC diagnostic ignored \"-Wc2y-extensions\"")
-#define BENCHMARK_RESTORE_COUNTER_WARNING _Pragma("GCC diagnostic pop")
-#else
-#define BENCHMARK_DISABLE_COUNTER_WARNING
-#define BENCHMARK_RESTORE_COUNTER_WARNING
-#endif
-// clang-format on
-
-// Check that __COUNTER__ is defined and that __COUNTER__ increases by 1
-// every time it is expanded. X + 1 == X + 0 is used in case X is defined to be
-// empty. If X is empty the expression becomes (+1 == +0).
-BENCHMARK_DISABLE_COUNTER_WARNING
-#if defined(__COUNTER__) && (__COUNTER__ + 1 == __COUNTER__ + 0)
-#define BENCHMARK_PRIVATE_UNIQUE_ID __COUNTER__
-#else
-#define BENCHMARK_PRIVATE_UNIQUE_ID __LINE__
-#endif
-BENCHMARK_RESTORE_COUNTER_WARNING
-
-// Helpers for generating unique variable names
-#define BENCHMARK_PRIVATE_NAME(...) \
- BENCHMARK_PRIVATE_CONCAT(benchmark_uniq_, BENCHMARK_PRIVATE_UNIQUE_ID, \
- __VA_ARGS__)
-
-#define BENCHMARK_PRIVATE_CONCAT(a, b, c) BENCHMARK_PRIVATE_CONCAT2(a, b, c)
-#define BENCHMARK_PRIVATE_CONCAT2(a, b, c) a##b##c
-// Helper for concatenation with macro name expansion
-#define BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method) \
- BaseClass##_##Method##_Benchmark
-
-#define BENCHMARK_PRIVATE_DECLARE(n) \
- BENCHMARK_DISABLE_COUNTER_WARNING \
- /* NOLINTNEXTLINE(misc-use-anonymous-namespace) */ \
- static ::benchmark::Benchmark const* const BENCHMARK_PRIVATE_NAME(n) \
- BENCHMARK_RESTORE_COUNTER_WARNING BENCHMARK_UNUSED
-
-#define BENCHMARK(...) \
- BENCHMARK_PRIVATE_DECLARE(_benchmark_) = \
- (::benchmark::internal::RegisterBenchmarkInternal( \
- ::benchmark::internal::make_unique< \
- ::benchmark::internal::FunctionBenchmark>( \
- #__VA_ARGS__, \
- static_cast<::benchmark::internal::Function*>(__VA_ARGS__))))
-
-// Old-style macros
-#define BENCHMARK_WITH_ARG(n, a) BENCHMARK(n)->Arg((a))
-#define BENCHMARK_WITH_ARG2(n, a1, a2) BENCHMARK(n)->Args({(a1), (a2)})
-#define BENCHMARK_WITH_UNIT(n, t) BENCHMARK(n)->Unit((t))
-#define BENCHMARK_RANGE(n, lo, hi) BENCHMARK(n)->Range((lo), (hi))
-#define BENCHMARK_RANGE2(n, l1, h1, l2, h2) \
- BENCHMARK(n)->RangePair({{(l1), (h1)}, {(l2), (h2)}})
-
-// Register a benchmark which invokes the function specified by `func`
-// with the additional arguments specified by `...`.
-//
-// For example:
-//
-// template <class ...ExtraArgs>`
-// void BM_takes_args(benchmark::State& state, ExtraArgs&&... extra_args) {
-// [...]
-//}
-// /* Registers a benchmark named "BM_takes_args/int_string_test` */
-// BENCHMARK_CAPTURE(BM_takes_args, int_string_test, 42, std::string("abc"));
-#define BENCHMARK_CAPTURE(func, test_case_name, ...) \
- BENCHMARK_PRIVATE_DECLARE(_benchmark_) = \
- (::benchmark::internal::RegisterBenchmarkInternal( \
- ::benchmark::internal::make_unique< \
- ::benchmark::internal::FunctionBenchmark>( \
- #func "/" #test_case_name, \
- [](::benchmark::State& st) { func(st, __VA_ARGS__); })))
-
-// Register a benchmark named `func/test_case_name` which invokes `func`
-// directly (no lambda, no extra arguments). Use this instead of
-// BENCHMARK_CAPTURE when you only need a custom name and do not need to
-// pass additional arguments. This avoids the lambda overhead that causes
-// compiler and linker scalability issues when registering large numbers of
-// benchmarks.
-//
-// For example:
-//
-// void BM_Foo(benchmark::State& state) {
-// for (auto _ : state) {}
-// }
-// /* Registers a benchmark named "BM_Foo/my_variant" */
-// BENCHMARK_NAMED(BM_Foo, my_variant);
-#define BENCHMARK_NAMED(func, test_case_name) \
- BENCHMARK_PRIVATE_DECLARE(_benchmark_) = \
- (::benchmark::internal::RegisterBenchmarkInternal( \
- ::benchmark::internal::make_unique< \
- ::benchmark::internal::FunctionBenchmark>( \
- #func "/" #test_case_name, \
- static_cast<::benchmark::internal::Function*>(func))))
-
-// This will register a benchmark for a templatized function. For example:
-//
-// template<int arg>
-// void BM_Foo(int iters);
-//
-// BENCHMARK_TEMPLATE(BM_Foo, 1);
-//
-// will register BM_Foo<1> as a benchmark.
-#define BENCHMARK_TEMPLATE1(n, a) \
- BENCHMARK_PRIVATE_DECLARE(n) = \
- (::benchmark::internal::RegisterBenchmarkInternal( \
- ::benchmark::internal::make_unique< \
- ::benchmark::internal::FunctionBenchmark>( \
- #n "<" #a ">", \
- static_cast<::benchmark::internal::Function*>(n<a>))))
-
-#define BENCHMARK_TEMPLATE2(n, a, b) \
- BENCHMARK_PRIVATE_DECLARE(n) = \
- (::benchmark::internal::RegisterBenchmarkInternal( \
- ::benchmark::internal::make_unique< \
- ::benchmark::internal::FunctionBenchmark>( \
- #n "<" #a "," #b ">", \
- static_cast<::benchmark::internal::Function*>(n<a, b>))))
-
-#define BENCHMARK_TEMPLATE(n, ...) \
- BENCHMARK_PRIVATE_DECLARE(n) = \
- (::benchmark::internal::RegisterBenchmarkInternal( \
- ::benchmark::internal::make_unique< \
- ::benchmark::internal::FunctionBenchmark>( \
- #n "<" #__VA_ARGS__ ">", \
- static_cast<::benchmark::internal::Function*>(n<__VA_ARGS__>))))
-
-// This will register a benchmark for a templatized function,
-// with the additional arguments specified by `...`.
-//
-// For example:
-//
-// template <typename T, class ...ExtraArgs>`
-// void BM_takes_args(benchmark::State& state, ExtraArgs&&... extra_args) {
-// [...]
-//}
-// /* Registers a benchmark named "BM_takes_args<void>/int_string_test` */
-// BENCHMARK_TEMPLATE1_CAPTURE(BM_takes_args, void, int_string_test, 42,
-// std::string("abc"));
-#define BENCHMARK_TEMPLATE1_CAPTURE(func, a, test_case_name, ...) \
- BENCHMARK_CAPTURE(func<a>, test_case_name, __VA_ARGS__)
-
-#define BENCHMARK_TEMPLATE2_CAPTURE(func, a, b, test_case_name, ...) \
- BENCHMARK_PRIVATE_DECLARE(func) = \
- (::benchmark::internal::RegisterBenchmarkInternal( \
- ::benchmark::internal::make_unique< \
- ::benchmark::internal::FunctionBenchmark>( \
- #func "<" #a "," #b ">" \
- "/" #test_case_name, \
- [](::benchmark::State& st) { func<a, b>(st, __VA_ARGS__); })))
-
-#define BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \
- class BaseClass##_##Method##_Benchmark : public BaseClass { \
- public: \
- BaseClass##_##Method##_Benchmark() { \
- this->SetName(#BaseClass "/" #Method); \
- } \
- \
- protected: \
- void BenchmarkCase(::benchmark::State&) override; \
- };
-
-#define BENCHMARK_TEMPLATE1_PRIVATE_DECLARE_F(BaseClass, Method, a) \
- class BaseClass##_##Method##_Benchmark : public BaseClass<a> { \
- public: \
- BaseClass##_##Method##_Benchmark() { \
- this->SetName(#BaseClass "<" #a ">/" #Method); \
- } \
- \
- protected: \
- void BenchmarkCase(::benchmark::State&) override; \
- };
-
-#define BENCHMARK_TEMPLATE2_PRIVATE_DECLARE_F(BaseClass, Method, a, b) \
- class BaseClass##_##Method##_Benchmark : public BaseClass<a, b> { \
- public: \
- BaseClass##_##Method##_Benchmark() { \
- this->SetName(#BaseClass "<" #a "," #b ">/" #Method); \
- } \
- \
- protected: \
- void BenchmarkCase(::benchmark::State&) override; \
- };
-
-#define BENCHMARK_TEMPLATE_PRIVATE_DECLARE_F(BaseClass, Method, ...) \
- class BaseClass##_##Method##_Benchmark : public BaseClass<__VA_ARGS__> { \
- public: \
- BaseClass##_##Method##_Benchmark() { \
- this->SetName(#BaseClass "<" #__VA_ARGS__ ">/" #Method); \
- } \
- \
- protected: \
- void BenchmarkCase(::benchmark::State&) override; \
- };
-
-#define BENCHMARK_DEFINE_F(BaseClass, Method) \
- BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \
- void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase
-
-#define BENCHMARK_TEMPLATE1_DEFINE_F(BaseClass, Method, a) \
- BENCHMARK_TEMPLATE1_PRIVATE_DECLARE_F(BaseClass, Method, a) \
- void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase
-
-#define BENCHMARK_TEMPLATE2_DEFINE_F(BaseClass, Method, a, b) \
- BENCHMARK_TEMPLATE2_PRIVATE_DECLARE_F(BaseClass, Method, a, b) \
- void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase
-
-#define BENCHMARK_TEMPLATE_DEFINE_F(BaseClass, Method, ...) \
- BENCHMARK_TEMPLATE_PRIVATE_DECLARE_F(BaseClass, Method, __VA_ARGS__) \
- void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase
-
-#define BENCHMARK_REGISTER_F(BaseClass, Method) \
- BENCHMARK_PRIVATE_REGISTER_F(BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method))
-
-#define BENCHMARK_PRIVATE_REGISTER_F(TestName) \
- BENCHMARK_PRIVATE_DECLARE(TestName) = \
- (::benchmark::internal::RegisterBenchmarkInternal( \
- ::benchmark::internal::make_unique<TestName>()))
-
-#define BENCHMARK_TEMPLATE_PRIVATE_CONCAT_NAME_F(BaseClass, Method) \
- BaseClass##_##Method##_BenchmarkTemplate
-
-#define BENCHMARK_TEMPLATE_METHOD_F(BaseClass, Method) \
- template <class... Args> \
- class BENCHMARK_TEMPLATE_PRIVATE_CONCAT_NAME_F(BaseClass, Method) \
- : public BaseClass<Args...> { \
- protected: \
- using Base = BaseClass<Args...>; \
- void BenchmarkCase(::benchmark::State&) override; \
- }; \
- template <class... Args> \
- void BENCHMARK_TEMPLATE_PRIVATE_CONCAT_NAME_F( \
- BaseClass, Method)<Args...>::BenchmarkCase
-
-#define BENCHMARK_TEMPLATE_PRIVATE_INSTANTIATE_F(BaseClass, Method, \
- UniqueName, ...) \
- class UniqueName : public BENCHMARK_TEMPLATE_PRIVATE_CONCAT_NAME_F( \
- BaseClass, Method)<__VA_ARGS__> { \
- public: \
- UniqueName() { this->SetName(#BaseClass "<" #__VA_ARGS__ ">/" #Method); } \
- }; \
- BENCHMARK_PRIVATE_DECLARE(BaseClass##_##Method##_Benchmark) = \
- (::benchmark::internal::RegisterBenchmarkInternal( \
- ::benchmark::internal::make_unique<UniqueName>()))
-
-#define BENCHMARK_TEMPLATE_INSTANTIATE_F(BaseClass, Method, ...) \
- BENCHMARK_DISABLE_COUNTER_WARNING \
- BENCHMARK_TEMPLATE_PRIVATE_INSTANTIATE_F( \
- BaseClass, Method, BENCHMARK_PRIVATE_NAME(BaseClass##Method), \
- __VA_ARGS__) \
- BENCHMARK_RESTORE_COUNTER_WARNING
-
-// This macro will define and register a benchmark within a fixture class.
-#define BENCHMARK_F(BaseClass, Method) \
- BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \
- BENCHMARK_REGISTER_F(BaseClass, Method); \
- void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase
-
-#define BENCHMARK_TEMPLATE1_F(BaseClass, Method, a) \
- BENCHMARK_TEMPLATE1_PRIVATE_DECLARE_F(BaseClass, Method, a) \
- BENCHMARK_REGISTER_F(BaseClass, Method); \
- void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase
-
-#define BENCHMARK_TEMPLATE2_F(BaseClass, Method, a, b) \
- BENCHMARK_TEMPLATE2_PRIVATE_DECLARE_F(BaseClass, Method, a, b) \
- BENCHMARK_REGISTER_F(BaseClass, Method); \
- void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase
-
-#define BENCHMARK_TEMPLATE_F(BaseClass, Method, ...) \
- BENCHMARK_TEMPLATE_PRIVATE_DECLARE_F(BaseClass, Method, __VA_ARGS__) \
- BENCHMARK_REGISTER_F(BaseClass, Method); \
- void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase
-
-// Helper macro to create a main routine in a test that runs the benchmarks
-// Note the workaround for Hexagon simulator passing argc != 0, argv = NULL.
-#define BENCHMARK_MAIN() \
- int main(int argc, char** argv) { \
- benchmark::MaybeReenterWithoutASLR(argc, argv); \
- char arg0_default[] = "benchmark"; \
- char* args_default = reinterpret_cast<char*>(arg0_default); \
- if (!argv) { \
- argc = 1; \
- argv = &args_default; \
- } \
- ::benchmark::Initialize(&argc, argv); \
- if (::benchmark::ReportUnrecognizedArguments(argc, argv)) return 1; \
- ::benchmark::RunSpecifiedBenchmarks(); \
- ::benchmark::Shutdown(); \
- return 0; \
- } \
- int main(int, char**)
-
-// ------------------------------------------------------
-// Benchmark Reporters
-
-namespace benchmark {
-
-struct BENCHMARK_EXPORT CPUInfo {
- struct CacheInfo {
- std::string type;
- int level;
- int size;
- int num_sharing;
- };
-
- enum Scaling { UNKNOWN, ENABLED, DISABLED };
-
- int num_cpus;
- Scaling scaling;
- double cycles_per_second;
- std::vector<CacheInfo> caches;
- std::vector<double> load_avg;
-
- static const CPUInfo& Get();
-
- private:
- CPUInfo();
- BENCHMARK_DISALLOW_COPY_AND_ASSIGN(CPUInfo);
-};
-
-// Adding Struct for System Information
-struct BENCHMARK_EXPORT SystemInfo {
- enum class ASLR { UNKNOWN, ENABLED, DISABLED };
-
- std::string name;
- ASLR ASLRStatus;
- static const SystemInfo& Get();
-
- private:
- SystemInfo();
- BENCHMARK_DISALLOW_COPY_AND_ASSIGN(SystemInfo);
-};
-
-// BenchmarkName contains the components of the Benchmark's name
-// which allows individual fields to be modified or cleared before
-// building the final name using 'str()'.
-struct BENCHMARK_EXPORT BenchmarkName {
- std::string function_name;
- std::string args;
- std::string min_time;
- std::string min_warmup_time;
- std::string iterations;
- std::string repetitions;
- std::string time_type;
- std::string threads;
-
- // Return the full name of the benchmark with each non-empty
- // field separated by a '/'
- std::string str() const;
-};
-
-// Interface for custom benchmark result printers.
-// By default, benchmark reports are printed to stdout. However an application
-// can control the destination of the reports by calling
-// RunSpecifiedBenchmarks and passing it a custom reporter object.
-// The reporter object must implement the following interface.
-class BENCHMARK_EXPORT BenchmarkReporter {
- public:
- struct Context {
- CPUInfo const& cpu_info;
- SystemInfo const& sys_info;
- // The number of chars in the longest benchmark name.
- size_t name_field_width = 0;
- static const char* executable_name;
- Context();
- };
-
- struct BENCHMARK_EXPORT Run {
- static const int64_t no_repetition_index = -1;
- enum RunType { RT_Iteration, RT_Aggregate };
-
- Run()
- : run_type(RT_Iteration),
- aggregate_unit(kTime),
- skipped(internal::NotSkipped),
- iterations(1),
- threads(1),
- time_unit(GetDefaultTimeUnit()),
- real_accumulated_time(0),
- cpu_accumulated_time(0),
- max_heapbytes_used(0),
- use_real_time_for_initial_big_o(false),
- complexity(oNone),
- complexity_lambda(),
- complexity_n(0),
- statistics(),
- report_big_o(false),
- report_rms(false),
- allocs_per_iter(0.0) {}
-
- std::string benchmark_name() const;
- BenchmarkName run_name;
- int64_t family_index;
- int64_t per_family_instance_index;
- RunType run_type;
- std::string aggregate_name;
- StatisticUnit aggregate_unit;
- std::string report_label; // Empty if not set by benchmark.
- internal::Skipped skipped;
- std::string skip_message;
-
- IterationCount iterations;
- int64_t threads;
- int64_t repetition_index;
- int64_t repetitions;
- TimeUnit time_unit;
- double real_accumulated_time;
- double cpu_accumulated_time;
-
- // Return a value representing the real time per iteration in the unit
- // specified by 'time_unit'.
- // NOTE: If 'iterations' is zero the returned value represents the
- // accumulated time.
- double GetAdjustedRealTime() const;
-
- // Return a value representing the cpu time per iteration in the unit
- // specified by 'time_unit'.
- // NOTE: If 'iterations' is zero the returned value represents the
- // accumulated time.
- double GetAdjustedCPUTime() const;
-
- // This is set to 0.0 if memory tracing is not enabled.
- double max_heapbytes_used;
-
- // By default Big-O is computed for CPU time, but that is not what you want
- // to happen when manual time was requested, which is stored as real time.
- bool use_real_time_for_initial_big_o;
-
- // Keep track of arguments to compute asymptotic complexity
- BigO complexity;
- BigOFunc* complexity_lambda;
- ComplexityN complexity_n;
-
- // what statistics to compute from the measurements
- const std::vector<internal::Statistics>* statistics;
-
- // Inform print function whether the current run is a complexity report
- bool report_big_o;
- bool report_rms;
-
- UserCounters counters;
-
- // Memory metrics.
- MemoryManager::Result memory_result;
- double allocs_per_iter;
- };
-
- struct PerFamilyRunReports {
- PerFamilyRunReports() : num_runs_total(0), num_runs_done(0) {}
-
- // How many runs will all instances of this benchmark perform?
- int num_runs_total;
-
- // How many runs have happened already?
- int num_runs_done;
-
- // The reports about (non-errneous!) runs of this family.
- std::vector<BenchmarkReporter::Run> Runs;
- };
-
- // Construct a BenchmarkReporter with the output stream set to 'std::cout'
- // and the error stream set to 'std::cerr'
- BenchmarkReporter();
-
- // Called once for every suite of benchmarks run.
- // The parameter "context" contains information that the
- // reporter may wish to use when generating its report, for example the
- // platform under which the benchmarks are running. The benchmark run is
- // never started if this function returns false, allowing the reporter
- // to skip runs based on the context information.
- virtual bool ReportContext(const Context& context) = 0;
-
- // Called once for each group of benchmark runs, gives information about
- // the configurations of the runs.
- virtual void ReportRunsConfig(double /*min_time*/,
- bool /*has_explicit_iters*/,
- IterationCount /*iters*/) {}
-
- // Called once for each group of benchmark runs, gives information about
- // cpu-time and heap memory usage during the benchmark run. If the group
- // of runs contained more than two entries then 'report' contains additional
- // elements representing the mean and standard deviation of those runs.
- // Additionally if this group of runs was the last in a family of benchmarks
- // 'reports' contains additional entries representing the asymptotic
- // complexity and RMS of that benchmark family.
- virtual void ReportRuns(const std::vector<Run>& report) = 0;
-
- // Called once and only once after ever group of benchmarks is run and
- // reported.
- virtual void Finalize() {}
-
- // REQUIRES: The object referenced by 'out' is valid for the lifetime
- // of the reporter.
- void SetOutputStream(std::ostream* out) {
- assert(out);
- output_stream_ = out;
- }
-
- // REQUIRES: The object referenced by 'err' is valid for the lifetime
- // of the reporter.
- void SetErrorStream(std::ostream* err) {
- assert(err);
- error_stream_ = err;
- }
-
- std::ostream& GetOutputStream() const { return *output_stream_; }
-
- std::ostream& GetErrorStream() const { return *error_stream_; }
-
- virtual ~BenchmarkReporter();
-
- // Write a human readable string to 'out' representing the specified
- // 'context'.
- // REQUIRES: 'out' is non-null.
- static void PrintBasicContext(std::ostream* out, Context const& context);
-
- private:
- std::ostream* output_stream_;
- std::ostream* error_stream_;
-};
-
-// Simple reporter that outputs benchmark data to the console. This is the
-// default reporter used by RunSpecifiedBenchmarks().
-class BENCHMARK_EXPORT ConsoleReporter : public BenchmarkReporter {
- public:
- enum OutputOptions {
- OO_None = 0,
- OO_Color = 1,
- OO_Tabular = 2,
- OO_ColorTabular = OO_Color | OO_Tabular,
- OO_Defaults = OO_ColorTabular
- };
- explicit ConsoleReporter(OutputOptions opts_ = OO_Defaults)
- : output_options_(opts_), name_field_width_(0), printed_header_(false) {}
-
- bool ReportContext(const Context& context) override;
- void ReportRuns(const std::vector<Run>& reports) override;
-
- protected:
- virtual void PrintRunData(const Run& result);
- virtual void PrintHeader(const Run& run);
-
- OutputOptions output_options_;
- size_t name_field_width_;
- UserCounters prev_counters_;
- bool printed_header_;
-};
-
-class BENCHMARK_EXPORT JSONReporter : public BenchmarkReporter {
- public:
- JSONReporter() : first_report_(true) {}
- bool ReportContext(const Context& context) override;
- void ReportRuns(const std::vector<Run>& reports) override;
- void Finalize() override;
-
- private:
- void PrintRunData(const Run& run);
-
- bool first_report_;
-};
-
-class BENCHMARK_EXPORT BENCHMARK_DEPRECATED_MSG(
- "The CSV Reporter will be removed in a future release") CSVReporter
- : public BenchmarkReporter {
- public:
- CSVReporter() : printed_header_(false) {}
- bool ReportContext(const Context& context) override;
- void ReportRuns(const std::vector<Run>& reports) override;
-
- private:
- void PrintRunData(const Run& run);
-
- bool printed_header_;
- std::set<std::string> user_counter_names_;
-};
-
-inline const char* GetTimeUnitString(TimeUnit unit) {
- switch (unit) {
- case kSecond:
- return "s";
- case kMillisecond:
- return "ms";
- case kMicrosecond:
- return "us";
- case kNanosecond:
- return "ns";
- }
- BENCHMARK_UNREACHABLE();
-}
-
-inline double GetTimeUnitMultiplier(TimeUnit unit) {
- switch (unit) {
- case kSecond:
- return 1;
- case kMillisecond:
- return 1e3;
- case kMicrosecond:
- return 1e6;
- case kNanosecond:
- return 1e9;
- }
- BENCHMARK_UNREACHABLE();
-}
-
-// Creates a list of integer values for the given range and multiplier.
-// This can be used together with ArgsProduct() to allow multiple ranges
-// with different multipliers.
-// Example:
-// ArgsProduct({
-// CreateRange(0, 1024, /*multi=*/32),
-// CreateRange(0, 100, /*multi=*/4),
-// CreateDenseRange(0, 4, /*step=*/1),
-// });
-BENCHMARK_EXPORT
-std::vector<int64_t> CreateRange(int64_t lo, int64_t hi, int multi);
-
-// Creates a list of integer values for the given range and step.
-BENCHMARK_EXPORT
-std::vector<int64_t> CreateDenseRange(int64_t start, int64_t limit, int step);
-
-} // namespace benchmark
-
-#if defined(_MSC_VER)
-#pragma warning(pop)
-#endif
+#include "benchmark/benchmark_api.h"
+#include "benchmark/counter.h"
+#include "benchmark/macros.h"
+#include "benchmark/managers.h"
+#include "benchmark/registration.h"
+#include "benchmark/reporter.h"
+#include "benchmark/state.h"
+#include "benchmark/statistics.h"
+#include "benchmark/sysinfo.h"
+#include "benchmark/types.h"
+#include "benchmark/utils.h"
#endif // BENCHMARK_BENCHMARK_H_
diff --git a/include/benchmark/benchmark_api.h b/include/benchmark/benchmark_api.h
new file mode 100644
index 0000000..6d98aba
--- /dev/null
+++ b/include/benchmark/benchmark_api.h
@@ -0,0 +1,292 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef BENCHMARK_BENCHMARK_API_H_
+#define BENCHMARK_BENCHMARK_API_H_
+
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable : 4251)
+#endif
+
+#include <functional>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "benchmark/counter.h"
+#include "benchmark/macros.h"
+#include "benchmark/state.h"
+#include "benchmark/statistics.h"
+#include "benchmark/types.h"
+
+namespace benchmark {
+
+const char kDefaultMinTimeStr[] = "0.5s";
+
+BENCHMARK_EXPORT void MaybeReenterWithoutASLR(int, char**);
+
+BENCHMARK_EXPORT std::string GetBenchmarkVersion();
+
+BENCHMARK_EXPORT void PrintDefaultHelp();
+
+BENCHMARK_EXPORT void Initialize(int* argc, char** argv,
+ void (*HelperPrintf)() = PrintDefaultHelp);
+BENCHMARK_EXPORT void Shutdown();
+
+BENCHMARK_EXPORT bool ReportUnrecognizedArguments(int argc, char** argv);
+
+BENCHMARK_EXPORT std::string GetBenchmarkFilter();
+
+BENCHMARK_EXPORT void SetBenchmarkFilter(std::string value);
+
+BENCHMARK_EXPORT int32_t GetBenchmarkVerbosity();
+
+BENCHMARK_EXPORT BenchmarkReporter* CreateDefaultDisplayReporter();
+
+BENCHMARK_EXPORT size_t RunSpecifiedBenchmarks();
+BENCHMARK_EXPORT size_t RunSpecifiedBenchmarks(std::string spec);
+
+BENCHMARK_EXPORT size_t
+RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter);
+BENCHMARK_EXPORT size_t
+RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter, std::string spec);
+
+BENCHMARK_EXPORT size_t RunSpecifiedBenchmarks(
+ BenchmarkReporter* display_reporter, BenchmarkReporter* file_reporter);
+BENCHMARK_EXPORT size_t
+RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter,
+ BenchmarkReporter* file_reporter, std::string spec);
+
+BENCHMARK_EXPORT TimeUnit GetDefaultTimeUnit();
+
+BENCHMARK_EXPORT void SetDefaultTimeUnit(TimeUnit unit);
+
+BENCHMARK_EXPORT
+void AddCustomContext(std::string key, std::string value);
+
+struct ThreadRunnerBase {
+ virtual ~ThreadRunnerBase() {}
+ virtual void RunThreads(const std::function<void(int)>& fn) = 0;
+};
+
+using threadrunner_factory =
+ std::function<std::unique_ptr<ThreadRunnerBase>(int)>;
+
+namespace internal {
+class BenchmarkFamilies;
+class BenchmarkInstance;
+} // namespace internal
+
+class BENCHMARK_EXPORT Benchmark {
+ public:
+ virtual ~Benchmark();
+
+ Benchmark* Name(const std::string& name);
+ Benchmark* Arg(int64_t x);
+ Benchmark* Unit(TimeUnit unit);
+ Benchmark* Range(int64_t start, int64_t limit);
+ Benchmark* DenseRange(int64_t start, int64_t limit, int step = 1);
+ Benchmark* Args(const std::vector<int64_t>& args);
+ Benchmark* ArgPair(int64_t x, int64_t y) {
+ std::vector<int64_t> args;
+ args.push_back(x);
+ args.push_back(y);
+ return Args(args);
+ }
+ Benchmark* Ranges(const std::vector<std::pair<int64_t, int64_t>>& ranges);
+ Benchmark* ArgsProduct(const std::vector<std::vector<int64_t>>& arglists);
+ Benchmark* ArgName(const std::string& name);
+ Benchmark* ArgNames(const std::vector<std::string>& names);
+ Benchmark* RangePair(int64_t lo1, int64_t hi1, int64_t lo2, int64_t hi2) {
+ std::vector<std::pair<int64_t, int64_t>> ranges;
+ ranges.push_back(std::make_pair(lo1, hi1));
+ ranges.push_back(std::make_pair(lo2, hi2));
+ return Ranges(ranges);
+ }
+ Benchmark* Setup(callback_function&&);
+ Benchmark* Setup(const callback_function&);
+ Benchmark* Teardown(callback_function&&);
+ Benchmark* Teardown(const callback_function&);
+ Benchmark* Apply(const std::function<void(Benchmark* benchmark)>&);
+ Benchmark* RangeMultiplier(int multiplier);
+ Benchmark* MinTime(double t);
+ Benchmark* MinWarmUpTime(double t);
+ Benchmark* Iterations(IterationCount n);
+ Benchmark* Repetitions(int n);
+ Benchmark* ReportAggregatesOnly(bool value = true);
+ Benchmark* DisplayAggregatesOnly(bool value = true);
+ Benchmark* MeasureProcessCPUTime();
+ Benchmark* UseRealTime();
+ Benchmark* UseManualTime();
+ Benchmark* Complexity(BigO complexity = benchmark::oAuto);
+ Benchmark* Complexity(BigOFunc* complexity);
+ Benchmark* ComputeStatistics(const std::string& name,
+ StatisticsFunc* statistics,
+ StatisticUnit unit = kTime);
+ Benchmark* Threads(int t);
+ Benchmark* ThreadRange(int min_threads, int max_threads);
+ Benchmark* DenseThreadRange(int min_threads, int max_threads, int stride = 1);
+ Benchmark* ThreadPerCpu();
+ Benchmark* ThreadRunner(threadrunner_factory&& factory);
+
+ virtual void Run(State& state) = 0;
+
+ TimeUnit GetTimeUnit() const;
+
+ protected:
+ explicit Benchmark(const std::string& name);
+ void SetName(const std::string& name);
+
+ public:
+ const char* GetName() const;
+ int ArgsCnt() const;
+ const char* GetArgName(int arg) const;
+
+ private:
+ friend class internal::BenchmarkFamilies;
+ friend class internal::BenchmarkInstance;
+
+ std::string name_;
+ internal::AggregationReportMode aggregation_report_mode_;
+ std::vector<std::string> arg_names_;
+ std::vector<std::vector<int64_t>> args_;
+
+ TimeUnit time_unit_;
+ bool use_default_time_unit_;
+
+ int range_multiplier_;
+ double min_time_;
+ double min_warmup_time_;
+ IterationCount iterations_;
+ int repetitions_;
+ bool measure_process_cpu_time_;
+ bool use_real_time_;
+ bool use_manual_time_;
+ BigO complexity_;
+ BigOFunc* complexity_lambda_;
+ std::vector<internal::Statistics> statistics_;
+ std::vector<int> thread_counts_;
+
+ callback_function setup_;
+ callback_function teardown_;
+
+ threadrunner_factory threadrunner_;
+
+ BENCHMARK_DISALLOW_COPY_AND_ASSIGN(Benchmark);
+};
+
+namespace internal {
+typedef BENCHMARK_DEPRECATED_MSG(
+ "Use ::benchmark::Benchmark instead")::benchmark::Benchmark Benchmark;
+typedef BENCHMARK_DEPRECATED_MSG(
+ "Use ::benchmark::threadrunner_factory instead")::benchmark::
+ threadrunner_factory threadrunner_factory;
+
+typedef void(Function)(State&);
+
+BENCHMARK_EXPORT ::benchmark::Benchmark* RegisterBenchmarkInternal(
+ std::unique_ptr<::benchmark::Benchmark>);
+BENCHMARK_EXPORT std::map<std::string, std::string>*& GetGlobalContext();
+BENCHMARK_EXPORT void UseCharPointer(char const volatile*);
+BENCHMARK_EXPORT int InitializeStreams();
+BENCHMARK_UNUSED static int stream_init_anchor = InitializeStreams();
+} // namespace internal
+
+Benchmark* RegisterBenchmark(const std::string& name, internal::Function* fn);
+
+template <class Lambda>
+Benchmark* RegisterBenchmark(const std::string& name, Lambda&& fn);
+
+BENCHMARK_EXPORT void ClearRegisteredBenchmarks();
+
+namespace internal {
+class BENCHMARK_EXPORT FunctionBenchmark : public benchmark::Benchmark {
+ public:
+ FunctionBenchmark(const std::string& name, Function* func)
+ : Benchmark(name), func_(func) {}
+ void Run(State& st) override;
+
+ private:
+ Function* func_;
+};
+
+template <class Lambda>
+class LambdaBenchmark : public benchmark::Benchmark {
+ public:
+ void Run(State& st) override { lambda_(st); }
+ template <class OLambda>
+ LambdaBenchmark(const std::string& name, OLambda&& lam)
+ : Benchmark(name), lambda_(std::forward<OLambda>(lam)) {}
+
+ private:
+ LambdaBenchmark(LambdaBenchmark const&) = delete;
+ Lambda lambda_;
+};
+} // namespace internal
+
+inline Benchmark* RegisterBenchmark(const std::string& name,
+ internal::Function* fn) {
+ return internal::RegisterBenchmarkInternal(
+ ::benchmark::internal::make_unique<internal::FunctionBenchmark>(name,
+ fn));
+}
+
+template <class Lambda>
+Benchmark* RegisterBenchmark(const std::string& name, Lambda&& fn) {
+ using BenchType =
+ internal::LambdaBenchmark<typename std::decay<Lambda>::type>;
+ return internal::RegisterBenchmarkInternal(
+ ::benchmark::internal::make_unique<BenchType>(name,
+ std::forward<Lambda>(fn)));
+}
+
+template <class Lambda, class... Args>
+Benchmark* RegisterBenchmark(const std::string& name, Lambda&& fn,
+ Args&&... args) {
+ return benchmark::RegisterBenchmark(
+ name, [=](benchmark::State& st) { fn(st, args...); });
+}
+
+class Fixture : public Benchmark {
+ public:
+ Fixture() : Benchmark("") {}
+ void Run(State& st) override {
+ this->SetUp(st);
+ this->BenchmarkCase(st);
+ this->TearDown(st);
+ }
+ virtual void SetUp(const State&) {}
+ virtual void TearDown(const State&) {}
+ virtual void SetUp(State& st) { SetUp(const_cast<const State&>(st)); }
+ virtual void TearDown(State& st) { TearDown(const_cast<const State&>(st)); }
+
+ protected:
+ virtual void BenchmarkCase(State&) = 0;
+};
+
+BENCHMARK_EXPORT
+std::vector<int64_t> CreateRange(int64_t lo, int64_t hi, int multi);
+
+BENCHMARK_EXPORT
+std::vector<int64_t> CreateDenseRange(int64_t start, int64_t limit, int step);
+
+} // namespace benchmark
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+#endif // BENCHMARK_BENCHMARK_API_H_
diff --git a/include/benchmark/counter.h b/include/benchmark/counter.h
new file mode 100644
index 0000000..8db5d8d
--- /dev/null
+++ b/include/benchmark/counter.h
@@ -0,0 +1,80 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef BENCHMARK_COUNTER_H_
+#define BENCHMARK_COUNTER_H_
+
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable : 4251)
+#endif
+
+#include <map>
+#include <string>
+
+#include "benchmark/macros.h"
+#include "benchmark/types.h"
+
+namespace benchmark {
+
+class BENCHMARK_EXPORT Counter {
+ public:
+ enum Flags {
+ kDefaults = 0,
+ kIsRate = 1 << 0,
+ kAvgThreads = 1 << 1,
+ kAvgThreadsRate = kIsRate | kAvgThreads,
+ kIsIterationInvariant = 1 << 2,
+ kIsIterationInvariantRate = kIsRate | kIsIterationInvariant,
+ kAvgIterations = 1 << 3,
+ kAvgIterationsRate = kIsRate | kAvgIterations,
+ kInvert = 1 << 31
+ };
+
+ enum OneK { kIs1000 = 1000, kIs1024 = 1024 };
+
+ double value;
+ Flags flags;
+ OneK oneK;
+
+ BENCHMARK_ALWAYS_INLINE
+ Counter(double v = 0., Flags f = kDefaults, OneK k = kIs1000)
+ : value(v), flags(f), oneK(k) {}
+
+ BENCHMARK_ALWAYS_INLINE operator double const&() const { return value; }
+ BENCHMARK_ALWAYS_INLINE operator double&() { return value; }
+};
+
+Counter::Flags inline operator|(const Counter::Flags& LHS,
+ const Counter::Flags& RHS) {
+ return static_cast<Counter::Flags>(static_cast<int>(LHS) |
+ static_cast<int>(RHS));
+}
+
+using UserCounters = std::map<std::string, Counter>;
+
+namespace internal {
+void Finish(UserCounters* l, IterationCount iterations, double cpu_time,
+ double num_threads);
+void Increment(UserCounters* l, UserCounters const& r);
+bool SameNames(UserCounters const& l, UserCounters const& r);
+} // namespace internal
+
+} // namespace benchmark
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+#endif // BENCHMARK_COUNTER_H_
diff --git a/include/benchmark/macros.h b/include/benchmark/macros.h
new file mode 100644
index 0000000..17f19ac
--- /dev/null
+++ b/include/benchmark/macros.h
@@ -0,0 +1,136 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef BENCHMARK_MACROS_H_
+#define BENCHMARK_MACROS_H_
+
+#if defined(_MSC_VER)
+#include <intrin.h>
+#endif
+
+#include <stdint.h>
+
+#define BENCHMARK_DISALLOW_COPY_AND_ASSIGN(TypeName) \
+ TypeName(const TypeName&) = delete; \
+ TypeName& operator=(const TypeName&) = delete
+
+#ifdef BENCHMARK_HAS_CXX17
+#define BENCHMARK_UNUSED [[maybe_unused]]
+#elif defined(__GNUC__) || defined(__clang__)
+#define BENCHMARK_UNUSED __attribute__((unused))
+#else
+#define BENCHMARK_UNUSED
+#endif
+
+#if defined(__clang__)
+#define BENCHMARK_DONT_OPTIMIZE __attribute__((optnone))
+#elif defined(__GNUC__) || defined(__GNUG__)
+#define BENCHMARK_DONT_OPTIMIZE __attribute__((optimize(0)))
+#else
+#define BENCHMARK_DONT_OPTIMIZE
+#endif
+
+#if defined(__GNUC__) || defined(__clang__)
+#define BENCHMARK_ALWAYS_INLINE __attribute__((always_inline))
+#elif defined(_MSC_VER) && !defined(__clang__)
+#define BENCHMARK_ALWAYS_INLINE __forceinline
+#define __func__ __FUNCTION__
+#else
+#define BENCHMARK_ALWAYS_INLINE
+#endif
+
+#define BENCHMARK_INTERNAL_TOSTRING2(x) #x
+#define BENCHMARK_INTERNAL_TOSTRING(x) BENCHMARK_INTERNAL_TOSTRING2(x)
+
+#if (defined(__GNUC__) && !defined(__NVCC__) && !defined(__NVCOMPILER)) || \
+ defined(__clang__)
+#define BENCHMARK_BUILTIN_EXPECT(x, y) __builtin_expect(x, y)
+#define BENCHMARK_DEPRECATED_MSG(msg) __attribute__((deprecated(msg)))
+#define BENCHMARK_DISABLE_DEPRECATED_WARNING \
+ _Pragma("GCC diagnostic push") \
+ _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
+#define BENCHMARK_RESTORE_DEPRECATED_WARNING _Pragma("GCC diagnostic pop")
+#elif defined(__NVCOMPILER)
+#define BENCHMARK_BUILTIN_EXPECT(x, y) __builtin_expect(x, y)
+#define BENCHMARK_DEPRECATED_MSG(msg) __attribute__((deprecated(msg)))
+#define BENCHMARK_DISABLE_DEPRECATED_WARNING \
+ _Pragma("diagnostic push") \
+ _Pragma("diag_suppress deprecated_entity_with_custom_message")
+#define BENCHMARK_RESTORE_DEPRECATED_WARNING _Pragma("diagnostic pop")
+#elif defined(_MSC_VER)
+#define BENCHMARK_BUILTIN_EXPECT(x, y) x
+#define BENCHMARK_DEPRECATED_MSG(msg) __declspec(deprecated(msg))
+#define BENCHMARK_WARNING_MSG(msg) \
+ __pragma(message(__FILE__ "(" BENCHMARK_INTERNAL_TOSTRING( \
+ __LINE__) ") : warning note: " msg))
+#define BENCHMARK_DISABLE_DEPRECATED_WARNING \
+ __pragma(warning(push)) __pragma(warning(disable : 4996))
+#define BENCHMARK_RESTORE_DEPRECATED_WARNING __pragma(warning(pop))
+#else
+#define BENCHMARK_BUILTIN_EXPECT(x, y) x
+#define BENCHMARK_DEPRECATED_MSG(msg)
+#define BENCHMARK_WARNING_MSG(msg) \
+ __pragma(message(__FILE__ "(" BENCHMARK_INTERNAL_TOSTRING( \
+ __LINE__) ") : warning note: " msg))
+#define BENCHMARK_DISABLE_DEPRECATED_WARNING
+#define BENCHMARK_RESTORE_DEPRECATED_WARNING
+#endif
+
+#if defined(__GNUC__) && !defined(__clang__)
+#define BENCHMARK_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
+#endif
+
+#ifndef __has_builtin
+#define __has_builtin(x) 0
+#endif
+
+#if defined(__GNUC__) || __has_builtin(__builtin_unreachable)
+#define BENCHMARK_UNREACHABLE() __builtin_unreachable()
+#elif defined(_MSC_VER)
+#define BENCHMARK_UNREACHABLE() __assume(false)
+#else
+#define BENCHMARK_UNREACHABLE() ((void)0)
+#endif
+
+#if defined(__GNUC__)
+#if defined(__i386__) || defined(__x86_64__)
+#define BENCHMARK_INTERNAL_CACHELINE_SIZE 64
+#elif defined(__powerpc64__)
+#define BENCHMARK_INTERNAL_CACHELINE_SIZE 128
+#elif defined(__aarch64__)
+#define BENCHMARK_INTERNAL_CACHELINE_SIZE 64
+#elif defined(__arm__)
+#if defined(__ARM_ARCH_5T__)
+#define BENCHMARK_INTERNAL_CACHELINE_SIZE 32
+#elif defined(__ARM_ARCH_7A__)
+#define BENCHMARK_INTERNAL_CACHELINE_SIZE 64
+#endif
+#endif
+#endif
+
+#ifndef BENCHMARK_INTERNAL_CACHELINE_SIZE
+#define BENCHMARK_INTERNAL_CACHELINE_SIZE 64
+#endif
+
+#if defined(__GNUC__)
+#define BENCHMARK_INTERNAL_CACHELINE_ALIGNED \
+ __attribute__((aligned(BENCHMARK_INTERNAL_CACHELINE_SIZE)))
+#elif defined(_MSC_VER)
+#define BENCHMARK_INTERNAL_CACHELINE_ALIGNED \
+ __declspec(align(BENCHMARK_INTERNAL_CACHELINE_SIZE))
+#else
+#define BENCHMARK_INTERNAL_CACHELINE_ALIGNED
+#endif
+
+#endif // BENCHMARK_MACROS_H_
diff --git a/include/benchmark/managers.h b/include/benchmark/managers.h
new file mode 100644
index 0000000..e8b6cd4
--- /dev/null
+++ b/include/benchmark/managers.h
@@ -0,0 +1,66 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef BENCHMARK_MANAGERS_H_
+#define BENCHMARK_MANAGERS_H_
+
+#include <stdint.h>
+
+#include <limits>
+
+#include "benchmark/macros.h"
+#include "benchmark/types.h"
+
+namespace benchmark {
+
+class MemoryManager {
+ public:
+ static constexpr int64_t TombstoneValue = std::numeric_limits<int64_t>::max();
+
+ struct Result {
+ Result()
+ : num_allocs(0),
+ max_bytes_used(0),
+ total_allocated_bytes(TombstoneValue),
+ net_heap_growth(TombstoneValue),
+ memory_iterations(0) {}
+
+ int64_t num_allocs;
+ int64_t max_bytes_used;
+ int64_t total_allocated_bytes;
+ int64_t net_heap_growth;
+ IterationCount memory_iterations;
+ };
+
+ virtual ~MemoryManager() {}
+ virtual void Start() = 0;
+ virtual void Stop(Result& result) = 0;
+};
+
+BENCHMARK_EXPORT
+void RegisterMemoryManager(MemoryManager* memory_manager);
+
+class ProfilerManager {
+ public:
+ virtual ~ProfilerManager() {}
+ virtual void AfterSetupStart() = 0;
+ virtual void BeforeTeardownStop() = 0;
+};
+
+BENCHMARK_EXPORT
+void RegisterProfilerManager(ProfilerManager* profiler_manager);
+
+} // namespace benchmark
+
+#endif // BENCHMARK_MANAGERS_H_
diff --git a/include/benchmark/registration.h b/include/benchmark/registration.h
new file mode 100644
index 0000000..5ac08de
--- /dev/null
+++ b/include/benchmark/registration.h
@@ -0,0 +1,258 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef BENCHMARK_REGISTRATION_H_
+#define BENCHMARK_REGISTRATION_H_
+
+#include "benchmark/benchmark_api.h"
+#include "benchmark/macros.h"
+
+#if defined(__clang__)
+#define BENCHMARK_DISABLE_COUNTER_WARNING \
+ _Pragma("GCC diagnostic push") \
+ _Pragma("GCC diagnostic ignored \"-Wunknown-warning-option\"") \
+ _Pragma("GCC diagnostic ignored \"-Wc2y-extensions\"")
+#define BENCHMARK_RESTORE_COUNTER_WARNING _Pragma("GCC diagnostic pop")
+#else
+#define BENCHMARK_DISABLE_COUNTER_WARNING
+#define BENCHMARK_RESTORE_COUNTER_WARNING
+#endif
+
+BENCHMARK_DISABLE_COUNTER_WARNING
+#if defined(__COUNTER__) && (__COUNTER__ + 1 == __COUNTER__ + 0)
+#define BENCHMARK_PRIVATE_UNIQUE_ID __COUNTER__
+#else
+#define BENCHMARK_PRIVATE_UNIQUE_ID __LINE__
+#endif
+BENCHMARK_RESTORE_COUNTER_WARNING
+
+#define BENCHMARK_PRIVATE_NAME(...) \
+ BENCHMARK_PRIVATE_CONCAT(benchmark_uniq_, BENCHMARK_PRIVATE_UNIQUE_ID, \
+ __VA_ARGS__)
+
+#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_CONCAT_NAME(BaseClass, Method) \
+ BaseClass##_##Method##_Benchmark
+
+#define BENCHMARK_PRIVATE_DECLARE(n) \
+ BENCHMARK_DISABLE_COUNTER_WARNING \
+ static ::benchmark::Benchmark const* const BENCHMARK_PRIVATE_NAME(n) \
+ BENCHMARK_RESTORE_COUNTER_WARNING BENCHMARK_UNUSED
+
+#define BENCHMARK(...) \
+ BENCHMARK_PRIVATE_DECLARE(_benchmark_) = \
+ (::benchmark::internal::RegisterBenchmarkInternal( \
+ ::benchmark::internal::make_unique< \
+ ::benchmark::internal::FunctionBenchmark>( \
+ #__VA_ARGS__, \
+ static_cast<::benchmark::internal::Function*>(__VA_ARGS__))))
+
+#define BENCHMARK_WITH_ARG(n, a) BENCHMARK(n)->Arg((a))
+#define BENCHMARK_WITH_ARG2(n, a1, a2) BENCHMARK(n)->Args({(a1), (a2)})
+#define BENCHMARK_WITH_UNIT(n, t) BENCHMARK(n)->Unit((t))
+#define BENCHMARK_RANGE(n, lo, hi) BENCHMARK(n)->Range((lo), (hi))
+#define BENCHMARK_RANGE2(n, l1, h1, l2, h2) \
+ BENCHMARK(n)->RangePair({{(l1), (h1)}, {(l2), (h2)}})
+
+#define BENCHMARK_CAPTURE(func, test_case_name, ...) \
+ BENCHMARK_PRIVATE_DECLARE(_benchmark_) = \
+ (::benchmark::internal::RegisterBenchmarkInternal( \
+ ::benchmark::internal::make_unique< \
+ ::benchmark::internal::FunctionBenchmark>( \
+ #func "/" #test_case_name, \
+ [](::benchmark::State& st) { func(st, __VA_ARGS__); })))
+
+#define BENCHMARK_NAMED(func, test_case_name) \
+ BENCHMARK_PRIVATE_DECLARE(_benchmark_) = \
+ (::benchmark::internal::RegisterBenchmarkInternal( \
+ ::benchmark::internal::make_unique< \
+ ::benchmark::internal::FunctionBenchmark>( \
+ #func "/" #test_case_name, \
+ static_cast<::benchmark::internal::Function*>(func))))
+
+#define BENCHMARK_TEMPLATE1(n, a) \
+ BENCHMARK_PRIVATE_DECLARE(n) = \
+ (::benchmark::internal::RegisterBenchmarkInternal( \
+ ::benchmark::internal::make_unique< \
+ ::benchmark::internal::FunctionBenchmark>( \
+ #n "<" #a ">", \
+ static_cast<::benchmark::internal::Function*>(n<a>))))
+
+#define BENCHMARK_TEMPLATE2(n, a, b) \
+ BENCHMARK_PRIVATE_DECLARE(n) = \
+ (::benchmark::internal::RegisterBenchmarkInternal( \
+ ::benchmark::internal::make_unique< \
+ ::benchmark::internal::FunctionBenchmark>( \
+ #n "<" #a "," #b ">", \
+ static_cast<::benchmark::internal::Function*>(n<a, b>))))
+
+#define BENCHMARK_TEMPLATE(n, ...) \
+ BENCHMARK_PRIVATE_DECLARE(n) = \
+ (::benchmark::internal::RegisterBenchmarkInternal( \
+ ::benchmark::internal::make_unique< \
+ ::benchmark::internal::FunctionBenchmark>( \
+ #n "<" #__VA_ARGS__ ">", \
+ static_cast<::benchmark::internal::Function*>(n<__VA_ARGS__>))))
+
+#define BENCHMARK_TEMPLATE1_CAPTURE(func, a, test_case_name, ...) \
+ BENCHMARK_CAPTURE(func<a>, test_case_name, __VA_ARGS__)
+
+#define BENCHMARK_TEMPLATE2_CAPTURE(func, a, b, test_case_name, ...) \
+ BENCHMARK_PRIVATE_DECLARE(func) = \
+ (::benchmark::internal::RegisterBenchmarkInternal( \
+ ::benchmark::internal::make_unique< \
+ ::benchmark::internal::FunctionBenchmark>( \
+ #func "<" #a "," #b ">" \
+ "/" #test_case_name, \
+ [](::benchmark::State& st) { func<a, b>(st, __VA_ARGS__); })))
+
+#define BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \
+ class BaseClass##_##Method##_Benchmark : public BaseClass { \
+ public: \
+ BaseClass##_##Method##_Benchmark() { \
+ this->SetName(#BaseClass "/" #Method); \
+ } \
+ \
+ protected: \
+ void BenchmarkCase(::benchmark::State&) override; \
+ };
+
+#define BENCHMARK_TEMPLATE1_PRIVATE_DECLARE_F(BaseClass, Method, a) \
+ class BaseClass##_##Method##_Benchmark : public BaseClass<a> { \
+ public: \
+ BaseClass##_##Method##_Benchmark() { \
+ this->SetName(#BaseClass "<" #a ">/" #Method); \
+ } \
+ \
+ protected: \
+ void BenchmarkCase(::benchmark::State&) override; \
+ };
+
+#define BENCHMARK_TEMPLATE2_PRIVATE_DECLARE_F(BaseClass, Method, a, b) \
+ class BaseClass##_##Method##_Benchmark : public BaseClass<a, b> { \
+ public: \
+ BaseClass##_##Method##_Benchmark() { \
+ this->SetName(#BaseClass "<" #a "," #b ">/" #Method); \
+ } \
+ \
+ protected: \
+ void BenchmarkCase(::benchmark::State&) override; \
+ };
+
+#define BENCHMARK_TEMPLATE_PRIVATE_DECLARE_F(BaseClass, Method, ...) \
+ class BaseClass##_##Method##_Benchmark : public BaseClass<__VA_ARGS__> { \
+ public: \
+ BaseClass##_##Method##_Benchmark() { \
+ this->SetName(#BaseClass "<" #__VA_ARGS__ ">/" #Method); \
+ } \
+ \
+ protected: \
+ void BenchmarkCase(::benchmark::State&) override; \
+ };
+
+#define BENCHMARK_DEFINE_F(BaseClass, Method) \
+ BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \
+ void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase
+
+#define BENCHMARK_TEMPLATE1_DEFINE_F(BaseClass, Method, a) \
+ BENCHMARK_TEMPLATE1_PRIVATE_DECLARE_F(BaseClass, Method, a) \
+ void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase
+
+#define BENCHMARK_TEMPLATE2_DEFINE_F(BaseClass, Method, a, b) \
+ BENCHMARK_TEMPLATE2_PRIVATE_DECLARE_F(BaseClass, Method, a, b) \
+ void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase
+
+#define BENCHMARK_TEMPLATE_DEFINE_F(BaseClass, Method, ...) \
+ BENCHMARK_TEMPLATE_PRIVATE_DECLARE_F(BaseClass, Method, __VA_ARGS__) \
+ void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase
+
+#define BENCHMARK_REGISTER_F(BaseClass, Method) \
+ BENCHMARK_PRIVATE_REGISTER_F(BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method))
+
+#define BENCHMARK_PRIVATE_REGISTER_F(TestName) \
+ BENCHMARK_PRIVATE_DECLARE(TestName) = \
+ (::benchmark::internal::RegisterBenchmarkInternal( \
+ ::benchmark::internal::make_unique<TestName>()))
+
+#define BENCHMARK_TEMPLATE_PRIVATE_CONCAT_NAME_F(BaseClass, Method) \
+ BaseClass##_##Method##_BenchmarkTemplate
+
+#define BENCHMARK_TEMPLATE_METHOD_F(BaseClass, Method) \
+ template <class... Args> \
+ class BENCHMARK_TEMPLATE_PRIVATE_CONCAT_NAME_F(BaseClass, Method) \
+ : public BaseClass<Args...> { \
+ protected: \
+ using Base = BaseClass<Args...>; \
+ void BenchmarkCase(::benchmark::State&) override; \
+ }; \
+ template <class... Args> \
+ void BENCHMARK_TEMPLATE_PRIVATE_CONCAT_NAME_F( \
+ BaseClass, Method)<Args...>::BenchmarkCase
+
+#define BENCHMARK_TEMPLATE_PRIVATE_INSTANTIATE_F(BaseClass, Method, \
+ UniqueName, ...) \
+ class UniqueName : public BENCHMARK_TEMPLATE_PRIVATE_CONCAT_NAME_F( \
+ BaseClass, Method)<__VA_ARGS__> { \
+ public: \
+ UniqueName() { this->SetName(#BaseClass "<" #__VA_ARGS__ ">/" #Method); } \
+ }; \
+ BENCHMARK_PRIVATE_DECLARE(BaseClass##_##Method##_Benchmark) = \
+ (::benchmark::internal::RegisterBenchmarkInternal( \
+ ::benchmark::internal::make_unique<UniqueName>()))
+
+#define BENCHMARK_TEMPLATE_INSTANTIATE_F(BaseClass, Method, ...) \
+ BENCHMARK_DISABLE_COUNTER_WARNING \
+ BENCHMARK_TEMPLATE_PRIVATE_INSTANTIATE_F( \
+ BaseClass, Method, BENCHMARK_PRIVATE_NAME(BaseClass##Method), \
+ __VA_ARGS__) \
+ BENCHMARK_RESTORE_COUNTER_WARNING
+
+#define BENCHMARK_F(BaseClass, Method) \
+ BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \
+ BENCHMARK_REGISTER_F(BaseClass, Method); \
+ void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase
+
+#define BENCHMARK_TEMPLATE1_F(BaseClass, Method, a) \
+ BENCHMARK_TEMPLATE1_PRIVATE_DECLARE_F(BaseClass, Method, a) \
+ BENCHMARK_REGISTER_F(BaseClass, Method); \
+ void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase
+
+#define BENCHMARK_TEMPLATE2_F(BaseClass, Method, a, b) \
+ BENCHMARK_TEMPLATE2_PRIVATE_DECLARE_F(BaseClass, Method, a, b) \
+ BENCHMARK_REGISTER_F(BaseClass, Method); \
+ void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase
+
+#define BENCHMARK_TEMPLATE_F(BaseClass, Method, ...) \
+ BENCHMARK_TEMPLATE_PRIVATE_DECLARE_F(BaseClass, Method, __VA_ARGS__) \
+ void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase
+
+#define BENCHMARK_MAIN() \
+ int main(int argc, char** argv) { \
+ benchmark::MaybeReenterWithoutASLR(argc, argv); \
+ char arg0_default[] = "benchmark"; \
+ char* args_default = reinterpret_cast<char*>(arg0_default); \
+ if (!argv) { \
+ argc = 1; \
+ argv = &args_default; \
+ } \
+ ::benchmark::Initialize(&argc, argv); \
+ if (::benchmark::ReportUnrecognizedArguments(argc, argv)) return 1; \
+ ::benchmark::RunSpecifiedBenchmarks(); \
+ ::benchmark::Shutdown(); \
+ return 0; \
+ } \
+ int main(int, char**)
+
+#endif // BENCHMARK_REGISTRATION_H_
diff --git a/include/benchmark/reporter.h b/include/benchmark/reporter.h
new file mode 100644
index 0000000..be242be
--- /dev/null
+++ b/include/benchmark/reporter.h
@@ -0,0 +1,238 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef BENCHMARK_REPORTER_H_
+#define BENCHMARK_REPORTER_H_
+
+#if defined(_MSC_VER)
+#pragma warning(push)
+// C4251: <symbol> needs to have dll-interface to be used by clients of class
+#pragma warning(disable : 4251)
+#endif
+
+#include <cassert>
+#include <iostream>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "benchmark/counter.h"
+#include "benchmark/macros.h"
+#include "benchmark/managers.h"
+#include "benchmark/statistics.h"
+#include "benchmark/sysinfo.h"
+#include "benchmark/types.h"
+
+namespace benchmark {
+
+struct BENCHMARK_EXPORT BenchmarkName {
+ std::string function_name;
+ std::string args;
+ std::string min_time;
+ std::string min_warmup_time;
+ std::string iterations;
+ std::string repetitions;
+ std::string time_type;
+ std::string threads;
+
+ std::string str() const;
+};
+
+class BENCHMARK_EXPORT BenchmarkReporter {
+ public:
+ struct Context {
+ CPUInfo const& cpu_info;
+ SystemInfo const& sys_info;
+ size_t name_field_width = 0;
+ static const char* executable_name;
+ Context();
+ };
+
+ struct BENCHMARK_EXPORT Run {
+ static const int64_t no_repetition_index = -1;
+ enum RunType { RT_Iteration, RT_Aggregate };
+
+ Run()
+ : run_type(RT_Iteration),
+ aggregate_unit(kTime),
+ skipped(internal::NotSkipped),
+ iterations(1),
+ threads(1),
+ time_unit(kNanosecond),
+ real_accumulated_time(0),
+ cpu_accumulated_time(0),
+ max_heapbytes_used(0),
+ use_real_time_for_initial_big_o(false),
+ complexity(oNone),
+ complexity_lambda(),
+ complexity_n(0),
+ statistics(),
+ report_big_o(false),
+ report_rms(false),
+ allocs_per_iter(0.0) {}
+
+ std::string benchmark_name() const;
+ BenchmarkName run_name;
+ int64_t family_index;
+ int64_t per_family_instance_index;
+ RunType run_type;
+ std::string aggregate_name;
+ StatisticUnit aggregate_unit;
+ std::string report_label;
+ internal::Skipped skipped;
+ std::string skip_message;
+
+ IterationCount iterations;
+ int64_t threads;
+ int64_t repetition_index;
+ int64_t repetitions;
+ TimeUnit time_unit;
+ double real_accumulated_time;
+ double cpu_accumulated_time;
+
+ double GetAdjustedRealTime() const;
+ double GetAdjustedCPUTime() const;
+
+ double max_heapbytes_used;
+ bool use_real_time_for_initial_big_o;
+ BigO complexity;
+ BigOFunc* complexity_lambda;
+ ComplexityN complexity_n;
+ const std::vector<internal::Statistics>* statistics;
+ bool report_big_o;
+ bool report_rms;
+ UserCounters counters;
+ MemoryManager::Result memory_result;
+ double allocs_per_iter;
+ };
+
+ struct PerFamilyRunReports {
+ PerFamilyRunReports() : num_runs_total(0), num_runs_done(0) {}
+ int num_runs_total;
+ int num_runs_done;
+ std::vector<BenchmarkReporter::Run> Runs;
+ };
+
+ BenchmarkReporter();
+ virtual bool ReportContext(const Context& context) = 0;
+ virtual void ReportRunsConfig(double /*min_time*/,
+ bool /*has_explicit_iters*/,
+ IterationCount /*iters*/) {}
+ virtual void ReportRuns(const std::vector<Run>& report) = 0;
+ virtual void Finalize() {}
+
+ void SetOutputStream(std::ostream* out) {
+ assert(out);
+ output_stream_ = out;
+ }
+ void SetErrorStream(std::ostream* err) {
+ assert(err);
+ error_stream_ = err;
+ }
+ std::ostream& GetOutputStream() const { return *output_stream_; }
+ std::ostream& GetErrorStream() const { return *error_stream_; }
+ virtual ~BenchmarkReporter();
+ static void PrintBasicContext(std::ostream* out, Context const& context);
+
+ private:
+ std::ostream* output_stream_;
+ std::ostream* error_stream_;
+};
+
+class BENCHMARK_EXPORT ConsoleReporter : public BenchmarkReporter {
+ public:
+ enum OutputOptions {
+ OO_None = 0,
+ OO_Color = 1,
+ OO_Tabular = 2,
+ OO_ColorTabular = OO_Color | OO_Tabular,
+ OO_Defaults = OO_ColorTabular
+ };
+ explicit ConsoleReporter(OutputOptions opts_ = OO_Defaults)
+ : output_options_(opts_), name_field_width_(0), printed_header_(false) {}
+
+ bool ReportContext(const Context& context) override;
+ void ReportRuns(const std::vector<Run>& reports) override;
+
+ protected:
+ virtual void PrintRunData(const Run& result);
+ virtual void PrintHeader(const Run& run);
+
+ OutputOptions output_options_;
+ size_t name_field_width_;
+ UserCounters prev_counters_;
+ bool printed_header_;
+};
+
+class BENCHMARK_EXPORT JSONReporter : public BenchmarkReporter {
+ public:
+ JSONReporter() : first_report_(true) {}
+ bool ReportContext(const Context& context) override;
+ void ReportRuns(const std::vector<Run>& reports) override;
+ void Finalize() override;
+
+ private:
+ void PrintRunData(const Run& run);
+ bool first_report_;
+};
+
+class BENCHMARK_EXPORT BENCHMARK_DEPRECATED_MSG(
+ "The CSV Reporter will be removed in a future release") CSVReporter
+ : public BenchmarkReporter {
+ public:
+ CSVReporter() : printed_header_(false) {}
+ bool ReportContext(const Context& context) override;
+ void ReportRuns(const std::vector<Run>& reports) override;
+
+ private:
+ void PrintRunData(const Run& run);
+ bool printed_header_;
+ std::set<std::string> user_counter_names_;
+};
+
+inline const char* GetTimeUnitString(TimeUnit unit) {
+ switch (unit) {
+ case kSecond:
+ return "s";
+ case kMillisecond:
+ return "ms";
+ case kMicrosecond:
+ return "us";
+ case kNanosecond:
+ return "ns";
+ }
+ BENCHMARK_UNREACHABLE();
+}
+
+inline double GetTimeUnitMultiplier(TimeUnit unit) {
+ switch (unit) {
+ case kSecond:
+ return 1;
+ case kMillisecond:
+ return 1e3;
+ case kMicrosecond:
+ return 1e6;
+ case kNanosecond:
+ return 1e9;
+ }
+ BENCHMARK_UNREACHABLE();
+}
+
+} // namespace benchmark
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+#endif // BENCHMARK_REPORTER_H_
diff --git a/include/benchmark/state.h b/include/benchmark/state.h
new file mode 100644
index 0000000..e9cdf05
--- /dev/null
+++ b/include/benchmark/state.h
@@ -0,0 +1,265 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef BENCHMARK_STATE_H_
+#define BENCHMARK_STATE_H_
+
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable : 4251 4324)
+#endif
+
+#include <cassert>
+#include <string>
+#include <vector>
+
+#include "benchmark/counter.h"
+#include "benchmark/macros.h"
+#include "benchmark/statistics.h"
+#include "benchmark/types.h"
+
+namespace benchmark {
+
+namespace internal {
+class BenchmarkInstance;
+class ThreadTimer;
+class ThreadManager;
+class PerfCountersMeasurement;
+} // namespace internal
+
+class ProfilerManager;
+
+class BENCHMARK_EXPORT BENCHMARK_INTERNAL_CACHELINE_ALIGNED State {
+ public:
+ struct StateIterator;
+ friend struct StateIterator;
+
+ inline BENCHMARK_ALWAYS_INLINE StateIterator begin();
+ inline BENCHMARK_ALWAYS_INLINE StateIterator end();
+
+ inline bool KeepRunning();
+
+ inline bool KeepRunningBatch(IterationCount n);
+
+ void PauseTiming();
+
+ void ResumeTiming();
+
+ void SkipWithMessage(const std::string& msg);
+
+ void SkipWithError(const std::string& msg);
+
+ bool skipped() const { return internal::NotSkipped != skipped_; }
+
+ bool error_occurred() const { return internal::SkippedWithError == skipped_; }
+
+ void SetIterationTime(double seconds);
+
+ BENCHMARK_ALWAYS_INLINE
+ void SetBytesProcessed(int64_t bytes) {
+ counters["bytes_per_second"] =
+ Counter(static_cast<double>(bytes), Counter::kIsRate, Counter::kIs1024);
+ }
+
+ BENCHMARK_ALWAYS_INLINE
+ int64_t bytes_processed() const {
+ if (counters.find("bytes_per_second") != counters.end())
+ return static_cast<int64_t>(counters.at("bytes_per_second"));
+ return 0;
+ }
+
+ BENCHMARK_ALWAYS_INLINE
+ void SetComplexityN(ComplexityN complexity_n) {
+ complexity_n_ = complexity_n;
+ }
+
+ BENCHMARK_ALWAYS_INLINE
+ ComplexityN complexity_length_n() const { return complexity_n_; }
+
+ BENCHMARK_ALWAYS_INLINE
+ void SetItemsProcessed(int64_t items) {
+ counters["items_per_second"] =
+ Counter(static_cast<double>(items), benchmark::Counter::kIsRate);
+ }
+
+ BENCHMARK_ALWAYS_INLINE
+ int64_t items_processed() const {
+ if (counters.find("items_per_second") != counters.end())
+ return static_cast<int64_t>(counters.at("items_per_second"));
+ return 0;
+ }
+
+ void SetLabel(const std::string& label);
+
+ BENCHMARK_ALWAYS_INLINE
+ int64_t range(std::size_t pos = 0) const {
+ assert(range_.size() > pos);
+ return range_[pos];
+ }
+
+ BENCHMARK_DEPRECATED_MSG("use 'range(0)' instead")
+ int64_t range_x() const { return range(0); }
+
+ BENCHMARK_DEPRECATED_MSG("use 'range(1)' instead")
+ int64_t range_y() const { return range(1); }
+
+ BENCHMARK_ALWAYS_INLINE
+ int threads() const { return threads_; }
+
+ BENCHMARK_ALWAYS_INLINE
+ int thread_index() const { return thread_index_; }
+
+ BENCHMARK_ALWAYS_INLINE
+ IterationCount iterations() const {
+ if (BENCHMARK_BUILTIN_EXPECT(!started_, false)) {
+ return 0;
+ }
+ return max_iterations - total_iterations_ + batch_leftover_;
+ }
+
+ BENCHMARK_ALWAYS_INLINE
+ std::string name() const { return name_; }
+
+ size_t range_size() const { return range_.size(); }
+
+ private:
+ IterationCount total_iterations_;
+
+ IterationCount batch_leftover_;
+
+ public:
+ const IterationCount max_iterations;
+
+ private:
+ bool started_;
+ bool finished_;
+ internal::Skipped skipped_;
+
+ std::vector<int64_t> range_;
+
+ ComplexityN complexity_n_;
+
+ public:
+ UserCounters counters;
+
+ private:
+ State(std::string name, IterationCount max_iters,
+ const std::vector<int64_t>& ranges, int thread_i, int n_threads,
+ internal::ThreadTimer* timer, internal::ThreadManager* manager,
+ internal::PerfCountersMeasurement* perf_counters_measurement,
+ ProfilerManager* profiler_manager);
+
+ void StartKeepRunning();
+ inline bool KeepRunningInternal(IterationCount n, bool is_batch);
+ void FinishKeepRunning();
+
+ const std::string name_;
+ const int thread_index_;
+ const int threads_;
+
+ internal::ThreadTimer* const timer_;
+ internal::ThreadManager* const manager_;
+ internal::PerfCountersMeasurement* const perf_counters_measurement_;
+ ProfilerManager* const profiler_manager_;
+
+ friend class internal::BenchmarkInstance;
+};
+
+inline BENCHMARK_ALWAYS_INLINE bool State::KeepRunning() {
+ return KeepRunningInternal(1, /*is_batch=*/false);
+}
+
+inline BENCHMARK_ALWAYS_INLINE bool State::KeepRunningBatch(IterationCount n) {
+ return KeepRunningInternal(n, /*is_batch=*/true);
+}
+
+inline BENCHMARK_ALWAYS_INLINE bool State::KeepRunningInternal(IterationCount n,
+ bool is_batch) {
+ assert(n > 0);
+ assert(is_batch || n == 1);
+ if (BENCHMARK_BUILTIN_EXPECT(total_iterations_ >= n, true)) {
+ total_iterations_ -= n;
+ return true;
+ }
+ if (!started_) {
+ StartKeepRunning();
+ if (!skipped() && total_iterations_ >= n) {
+ total_iterations_ -= n;
+ return true;
+ }
+ }
+ if (is_batch && total_iterations_ != 0) {
+ batch_leftover_ = n - total_iterations_;
+ total_iterations_ = 0;
+ return true;
+ }
+ FinishKeepRunning();
+ return false;
+}
+
+struct State::StateIterator {
+ struct BENCHMARK_UNUSED Value {};
+ typedef std::forward_iterator_tag iterator_category;
+ typedef Value value_type;
+ typedef Value reference;
+ typedef Value pointer;
+ typedef std::ptrdiff_t difference_type;
+
+ private:
+ friend class State;
+ BENCHMARK_ALWAYS_INLINE
+ StateIterator() : cached_(0), parent_() {}
+
+ BENCHMARK_ALWAYS_INLINE
+ explicit StateIterator(State* st)
+ : cached_(st->skipped() ? 0 : st->max_iterations), parent_(st) {}
+
+ public:
+ BENCHMARK_ALWAYS_INLINE
+ Value operator*() const { return Value(); }
+
+ BENCHMARK_ALWAYS_INLINE
+ StateIterator& operator++() {
+ assert(cached_ > 0);
+ --cached_;
+ return *this;
+ }
+
+ BENCHMARK_ALWAYS_INLINE
+ bool operator!=(StateIterator const&) const {
+ if (BENCHMARK_BUILTIN_EXPECT(cached_ != 0, true)) return true;
+ parent_->FinishKeepRunning();
+ return false;
+ }
+
+ private:
+ IterationCount cached_;
+ State* const parent_;
+};
+
+inline BENCHMARK_ALWAYS_INLINE State::StateIterator State::begin() {
+ return StateIterator(this);
+}
+inline BENCHMARK_ALWAYS_INLINE State::StateIterator State::end() {
+ StartKeepRunning();
+ return StateIterator();
+}
+
+} // namespace benchmark
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+#endif // BENCHMARK_STATE_H_
diff --git a/include/benchmark/statistics.h b/include/benchmark/statistics.h
new file mode 100644
index 0000000..04f01b1
--- /dev/null
+++ b/include/benchmark/statistics.h
@@ -0,0 +1,65 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef BENCHMARK_STATISTICS_H_
+#define BENCHMARK_STATISTICS_H_
+
+#include <string>
+#include <vector>
+
+#include "benchmark/types.h"
+
+namespace benchmark {
+
+enum BigO { oNone, o1, oN, oNSquared, oNCubed, oLogN, oNLogN, oAuto, oLambda };
+
+typedef int64_t ComplexityN;
+
+enum StatisticUnit { kTime, kPercentage };
+
+typedef double(BigOFunc)(ComplexityN);
+
+typedef double(StatisticsFunc)(const std::vector<double>&);
+
+namespace internal {
+struct Statistics {
+ std::string name_;
+ StatisticsFunc* compute_;
+ StatisticUnit unit_;
+
+ Statistics(const std::string& name, StatisticsFunc* compute,
+ StatisticUnit unit = kTime)
+ : name_(name), compute_(compute), unit_(unit) {}
+};
+
+enum AggregationReportMode : unsigned {
+ ARM_Unspecified = 0,
+ ARM_Default = 1U << 0U,
+ ARM_FileReportAggregatesOnly = 1U << 1U,
+ ARM_DisplayReportAggregatesOnly = 1U << 2U,
+ ARM_ReportAggregatesOnly =
+ ARM_FileReportAggregatesOnly | ARM_DisplayReportAggregatesOnly
+};
+
+enum Skipped : unsigned {
+ NotSkipped = 0,
+ SkippedWithMessage,
+ SkippedWithError
+};
+
+} // namespace internal
+
+} // namespace benchmark
+
+#endif // BENCHMARK_STATISTICS_H_
diff --git a/include/benchmark/sysinfo.h b/include/benchmark/sysinfo.h
new file mode 100644
index 0000000..711e64d
--- /dev/null
+++ b/include/benchmark/sysinfo.h
@@ -0,0 +1,71 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef BENCHMARK_SYSINFO_H_
+#define BENCHMARK_SYSINFO_H_
+
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable : 4251)
+#endif
+
+#include <string>
+#include <vector>
+
+#include "benchmark/macros.h"
+
+namespace benchmark {
+
+struct BENCHMARK_EXPORT CPUInfo {
+ struct CacheInfo {
+ std::string type;
+ int level;
+ int size;
+ int num_sharing;
+ };
+
+ enum Scaling { UNKNOWN, ENABLED, DISABLED };
+
+ int num_cpus;
+ Scaling scaling;
+ double cycles_per_second;
+ std::vector<CacheInfo> caches;
+ std::vector<double> load_avg;
+
+ static const CPUInfo& Get();
+
+ private:
+ CPUInfo();
+ BENCHMARK_DISALLOW_COPY_AND_ASSIGN(CPUInfo);
+};
+
+struct BENCHMARK_EXPORT SystemInfo {
+ enum class ASLR { UNKNOWN, ENABLED, DISABLED };
+
+ std::string name;
+ ASLR ASLRStatus;
+ static const SystemInfo& Get();
+
+ private:
+ SystemInfo();
+ BENCHMARK_DISALLOW_COPY_AND_ASSIGN(SystemInfo);
+};
+
+} // namespace benchmark
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+#endif // BENCHMARK_SYSINFO_H_
diff --git a/include/benchmark/types.h b/include/benchmark/types.h
new file mode 100644
index 0000000..a82ffb9
--- /dev/null
+++ b/include/benchmark/types.h
@@ -0,0 +1,50 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef BENCHMARK_TYPES_H_
+#define BENCHMARK_TYPES_H_
+
+#include <stdint.h>
+
+#include <functional>
+#include <memory>
+#include <string>
+
+#include "benchmark/export.h"
+
+namespace benchmark {
+
+namespace internal {
+#if (__cplusplus < 201402L || (defined(_MSC_VER) && _MSVC_LANG < 201402L))
+template <typename T, typename... Args>
+std::unique_ptr<T> make_unique(Args&&... args) {
+ return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
+}
+#else
+using ::std::make_unique;
+#endif
+} // namespace internal
+
+class BenchmarkReporter;
+class State;
+
+using IterationCount = int64_t;
+
+using callback_function = std::function<void(const benchmark::State&)>;
+
+enum TimeUnit { kNanosecond, kMicrosecond, kMillisecond, kSecond };
+
+} // namespace benchmark
+
+#endif // BENCHMARK_TYPES_H_
diff --git a/include/benchmark/utils.h b/include/benchmark/utils.h
new file mode 100644
index 0000000..2be0d3f
--- /dev/null
+++ b/include/benchmark/utils.h
@@ -0,0 +1,152 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef BENCHMARK_UTILS_H_
+#define BENCHMARK_UTILS_H_
+
+#include <atomic>
+#include <type_traits>
+#include <utility>
+
+#include "benchmark/macros.h"
+
+namespace benchmark {
+
+namespace internal {
+BENCHMARK_EXPORT void UseCharPointer(char const volatile*);
+}
+
+#if (!defined(__GNUC__) && !defined(__clang__)) || defined(__pnacl__) || \
+ defined(__EMSCRIPTEN__)
+#define BENCHMARK_HAS_NO_INLINE_ASSEMBLY
+#endif
+
+inline BENCHMARK_ALWAYS_INLINE void ClobberMemory() {
+ std::atomic_signal_fence(std::memory_order_acq_rel);
+}
+
+#ifndef BENCHMARK_HAS_NO_INLINE_ASSEMBLY
+#if !defined(__GNUC__) || defined(__llvm__) || defined(__INTEL_COMPILER)
+template <class Tp>
+BENCHMARK_DEPRECATED_MSG(
+ "The const-ref version of this method can permit "
+ "undesired compiler optimizations in benchmarks")
+inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) {
+ asm volatile("" : : "r,m"(value) : "memory");
+}
+
+template <class Tp>
+inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp& value) {
+#if defined(__clang__)
+ asm volatile("" : "+r,m"(value) : : "memory");
+#else
+ asm volatile("" : "+m,r"(value) : : "memory");
+#endif
+}
+
+template <class Tp>
+inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp&& value) {
+#if defined(__clang__)
+ asm volatile("" : "+r,m"(value) : : "memory");
+#else
+ asm volatile("" : "+m,r"(value) : : "memory");
+#endif
+}
+#elif (__GNUC__ >= 5)
+template <class Tp>
+BENCHMARK_DEPRECATED_MSG(
+ "The const-ref version of this method can permit "
+ "undesired compiler optimizations in benchmarks")
+inline BENCHMARK_ALWAYS_INLINE
+ typename std::enable_if<std::is_trivially_copyable<Tp>::value &&
+ (sizeof(Tp) <= sizeof(Tp*))>::type
+ DoNotOptimize(Tp const& value) {
+ asm volatile("" : : "r,m"(value) : "memory");
+}
+
+template <class Tp>
+BENCHMARK_DEPRECATED_MSG(
+ "The const-ref version of this method can permit "
+ "undesired compiler optimizations in benchmarks")
+inline BENCHMARK_ALWAYS_INLINE
+ typename std::enable_if<!std::is_trivially_copyable<Tp>::value ||
+ (sizeof(Tp) > sizeof(Tp*))>::type
+ DoNotOptimize(Tp const& value) {
+ asm volatile("" : : "m"(value) : "memory");
+}
+
+template <class Tp>
+inline BENCHMARK_ALWAYS_INLINE
+ typename std::enable_if<std::is_trivially_copyable<Tp>::value &&
+ (sizeof(Tp) <= sizeof(Tp*))>::type
+ DoNotOptimize(Tp& value) {
+ asm volatile("" : "+m,r"(value) : : "memory");
+}
+
+template <class Tp>
+inline BENCHMARK_ALWAYS_INLINE
+ typename std::enable_if<!std::is_trivially_copyable<Tp>::value ||
+ (sizeof(Tp) > sizeof(Tp*))>::type
+ DoNotOptimize(Tp& value) {
+ asm volatile("" : "+m"(value) : : "memory");
+}
+
+template <class Tp>
+inline BENCHMARK_ALWAYS_INLINE
+ typename std::enable_if<std::is_trivially_copyable<Tp>::value &&
+ (sizeof(Tp) <= sizeof(Tp*))>::type
+ DoNotOptimize(Tp&& value) {
+ asm volatile("" : "+m,r"(value) : : "memory");
+}
+
+template <class Tp>
+inline BENCHMARK_ALWAYS_INLINE
+ typename std::enable_if<!std::is_trivially_copyable<Tp>::value ||
+ (sizeof(Tp) > sizeof(Tp*))>::type
+ DoNotOptimize(Tp&& value) {
+ asm volatile("" : "+m"(value) : : "memory");
+}
+#endif
+
+#elif defined(_MSC_VER)
+template <class Tp>
+BENCHMARK_DEPRECATED_MSG(
+ "The const-ref version of this method can permit "
+ "undesired compiler optimizations in benchmarks")
+inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) {
+ internal::UseCharPointer(&reinterpret_cast<char const volatile&>(value));
+ _ReadWriteBarrier();
+}
+
+template <class Tp>
+inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp& value) {
+ internal::UseCharPointer(&reinterpret_cast<char const volatile&>(value));
+ _ReadWriteBarrier();
+}
+
+template <class Tp>
+inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp&& value) {
+ internal::UseCharPointer(&reinterpret_cast<char const volatile&>(value));
+ _ReadWriteBarrier();
+}
+#else
+template <class Tp>
+inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp&& value) {
+ internal::UseCharPointer(&reinterpret_cast<char const volatile&>(value));
+}
+#endif
+
+} // end namespace benchmark
+
+#endif // BENCHMARK_UTILS_H_
diff --git a/src/benchmark.cc b/src/benchmark.cc
index fc36fed..acf4d3b 100644
--- a/src/benchmark.cc
+++ b/src/benchmark.cc
@@ -12,8 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "benchmark/benchmark.h"
-
+#include "benchmark/benchmark_api.h"
+#include "benchmark/registration.h"
+#include "benchmark/reporter.h"
+#include "benchmark/state.h"
+#include "benchmark/types.h"
#include "benchmark_api_internal.h"
#include "benchmark_runner.h"
#include "internal_macros.h"
diff --git a/src/benchmark_api_internal.h b/src/benchmark_api_internal.h
index 5b48ea2..0f356da 100644
--- a/src/benchmark_api_internal.h
+++ b/src/benchmark_api_internal.h
@@ -8,7 +8,9 @@
#include <string>
#include <vector>
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/reporter.h"
+#include "benchmark/sysinfo.h"
#include "commandlineflags.h"
namespace benchmark {
diff --git a/src/benchmark_main.cc b/src/benchmark_main.cc
index 15c76ea..0501643 100644
--- a/src/benchmark_main.cc
+++ b/src/benchmark_main.cc
@@ -12,7 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "benchmark/benchmark.h"
+#include "benchmark/export.h"
+#include "benchmark/registration.h"
BENCHMARK_EXPORT int main(int /*argc*/, char** /*argv*/);
BENCHMARK_MAIN();
diff --git a/src/benchmark_name.cc b/src/benchmark_name.cc
index 804cfbd..710eb6d 100644
--- a/src/benchmark_name.cc
+++ b/src/benchmark_name.cc
@@ -12,7 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include <benchmark/benchmark.h>
+#include "benchmark/export.h"
+#include "benchmark/reporter.h"
namespace benchmark {
diff --git a/src/benchmark_register.cc b/src/benchmark_register.cc
index 65e1afc..730d275 100644
--- a/src/benchmark_register.cc
+++ b/src/benchmark_register.cc
@@ -36,7 +36,11 @@
#include <sstream>
#include <thread>
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/registration.h"
+#include "benchmark/reporter.h"
+#include "benchmark/statistics.h"
+#include "benchmark/types.h"
#include "benchmark_api_internal.h"
#include "check.h"
#include "commandlineflags.h"
diff --git a/src/benchmark_runner.cc b/src/benchmark_runner.cc
index fb68867..7efbad4 100644
--- a/src/benchmark_runner.cc
+++ b/src/benchmark_runner.cc
@@ -14,7 +14,11 @@
#include "benchmark_runner.h"
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/managers.h"
+#include "benchmark/reporter.h"
+#include "benchmark/state.h"
+#include "benchmark/types.h"
#include "benchmark_api_internal.h"
#include "internal_macros.h"
diff --git a/src/complexity.cc b/src/complexity.cc
index 4c9ef6d..8fa3f07 100644
--- a/src/complexity.cc
+++ b/src/complexity.cc
@@ -19,7 +19,9 @@
#include <cmath>
-#include "benchmark/benchmark.h"
+#include "benchmark/reporter.h"
+#include "benchmark/statistics.h"
+#include "benchmark/types.h"
#include "check.h"
namespace benchmark {
diff --git a/src/complexity.h b/src/complexity.h
index 0a0679b..06002be 100644
--- a/src/complexity.h
+++ b/src/complexity.h
@@ -21,7 +21,8 @@
#include <string>
#include <vector>
-#include "benchmark/benchmark.h"
+#include "benchmark/reporter.h"
+#include "benchmark/statistics.h"
namespace benchmark {
diff --git a/src/console_reporter.cc b/src/console_reporter.cc
index a7cde4e..84fe99d 100644
--- a/src/console_reporter.cc
+++ b/src/console_reporter.cc
@@ -21,7 +21,9 @@
#include <tuple>
#include <vector>
-#include "benchmark/benchmark.h"
+#include "benchmark/export.h"
+#include "benchmark/reporter.h"
+#include "benchmark/types.h"
#include "check.h"
#include "colorprint.h"
#include "commandlineflags.h"
diff --git a/src/counter.h b/src/counter.h
index 1f5a58e..811a667 100644
--- a/src/counter.h
+++ b/src/counter.h
@@ -12,14 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef BENCHMARK_COUNTER_H_
-#define BENCHMARK_COUNTER_H_
+#ifndef BENCHMARK_SRC_COUNTER_H_
+#define BENCHMARK_SRC_COUNTER_H_
-#include "benchmark/benchmark.h"
+#include "benchmark/counter.h"
+#include "benchmark/export.h"
+#include "benchmark/types.h"
namespace benchmark {
-// these counter-related functions are hidden to reduce API surface.
namespace internal {
void Finish(UserCounters* l, IterationCount iterations, double time,
double num_threads);
@@ -29,4 +30,4 @@
} // end namespace benchmark
-#endif // BENCHMARK_COUNTER_H_
+#endif // BENCHMARK_SRC_COUNTER_H_
diff --git a/src/csv_reporter.cc b/src/csv_reporter.cc
index 0f99804..1665ac5 100644
--- a/src/csv_reporter.cc
+++ b/src/csv_reporter.cc
@@ -16,7 +16,8 @@
#include <string>
#include <vector>
-#include "benchmark/benchmark.h"
+#include "benchmark/export.h"
+#include "benchmark/reporter.h"
#include "check.h"
#include "complexity.h"
diff --git a/src/cycleclock.h b/src/cycleclock.h
index 0671a42..2633f22 100644
--- a/src/cycleclock.h
+++ b/src/cycleclock.h
@@ -23,7 +23,7 @@
#include <cstdint>
-#include "benchmark/benchmark.h"
+#include "benchmark/macros.h"
#include "internal_macros.h"
#if defined(BENCHMARK_OS_MACOSX)
diff --git a/src/json_reporter.cc b/src/json_reporter.cc
index 2b84cd1..ef4636e 100644
--- a/src/json_reporter.cc
+++ b/src/json_reporter.cc
@@ -22,7 +22,10 @@
#include <tuple>
#include <vector>
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/export.h"
+#include "benchmark/reporter.h"
+#include "benchmark/types.h"
#include "complexity.h"
#include "string_util.h"
#include "timers.h"
diff --git a/src/perf_counters.h b/src/perf_counters.h
index 4e45344..23cdcc3 100644
--- a/src/perf_counters.h
+++ b/src/perf_counters.h
@@ -16,12 +16,15 @@
#define BENCHMARK_PERF_COUNTERS_H
#include <array>
+#include <cassert>
#include <cstdint>
#include <cstring>
#include <memory>
#include <vector>
-#include "benchmark/benchmark.h"
+#include "benchmark/export.h"
+#include "benchmark/macros.h"
+#include "benchmark/utils.h"
#include "check.h"
#include "log.h"
#include "mutex.h"
diff --git a/src/reporter.cc b/src/reporter.cc
index 71926b1..73ca8d0 100644
--- a/src/reporter.cc
+++ b/src/reporter.cc
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include "benchmark/reporter.h"
+
#include <cstdlib>
#include <iostream>
#include <map>
@@ -19,7 +21,8 @@
#include <tuple>
#include <vector>
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/sysinfo.h"
#include "check.h"
#include "string_util.h"
#include "timers.h"
@@ -31,10 +34,10 @@
BenchmarkReporter::~BenchmarkReporter() {}
-void BenchmarkReporter::PrintBasicContext(std::ostream *out,
- Context const &context) {
+void BenchmarkReporter::PrintBasicContext(std::ostream* out,
+ Context const& context) {
BM_CHECK(out) << "cannot be null";
- auto &Out = *out;
+ auto& Out = *out;
#ifndef BENCHMARK_OS_QURT
// Date/time information is not available on QuRT.
@@ -47,13 +50,13 @@
<< "\n";
}
- const CPUInfo &info = context.cpu_info;
+ const CPUInfo& info = context.cpu_info;
Out << "Run on (" << info.num_cpus << " X "
<< (info.cycles_per_second / 1000000.0) << " MHz CPU "
<< ((info.num_cpus > 1) ? "s" : "") << ")\n";
if (!info.caches.empty()) {
Out << "CPU Caches:\n";
- for (const auto &CInfo : info.caches) {
+ for (const auto& CInfo : info.caches) {
Out << " L" << CInfo.level << " " << CInfo.type << " "
<< (CInfo.size / 1024) << " KiB";
if (CInfo.num_sharing != 0) {
@@ -73,11 +76,11 @@
Out << "\n";
}
- std::map<std::string, std::string> *global_context =
+ std::map<std::string, std::string>* global_context =
internal::GetGlobalContext();
if (global_context != nullptr) {
- for (const auto &kv : *global_context) {
+ for (const auto& kv : *global_context) {
Out << kv.first << ": " << kv.second << "\n";
}
}
@@ -88,7 +91,7 @@
"overhead.\n";
}
- const SystemInfo &sysinfo = context.sys_info;
+ const SystemInfo& sysinfo = context.sys_info;
if (SystemInfo::ASLR::ENABLED == sysinfo.ASLRStatus) {
Out << "***WARNING*** ASLR is enabled, the results may have unreproducible "
"noise in them.\n";
@@ -101,7 +104,7 @@
}
// No initializer because it's already initialized to NULL.
-const char *BenchmarkReporter::Context::executable_name;
+const char* BenchmarkReporter::Context::executable_name;
BenchmarkReporter::Context::Context()
: cpu_info(CPUInfo::Get()), sys_info(SystemInfo::Get()) {}
diff --git a/src/statistics.cc b/src/statistics.cc
index fc7450e..2c6c858 100644
--- a/src/statistics.cc
+++ b/src/statistics.cc
@@ -21,7 +21,9 @@
#include <string>
#include <vector>
-#include "benchmark/benchmark.h"
+#include "benchmark/reporter.h"
+#include "benchmark/statistics.h"
+#include "benchmark/types.h"
#include "check.h"
namespace benchmark {
diff --git a/src/statistics.h b/src/statistics.h
index 6e5560e..2e56c53 100644
--- a/src/statistics.h
+++ b/src/statistics.h
@@ -18,7 +18,8 @@
#include <vector>
-#include "benchmark/benchmark.h"
+#include "benchmark/export.h"
+#include "benchmark/reporter.h"
namespace benchmark {
diff --git a/src/string_util.cc b/src/string_util.cc
index aa36cf9..ae9667b 100644
--- a/src/string_util.cc
+++ b/src/string_util.cc
@@ -11,7 +11,7 @@
#include <sstream>
#include "arraysize.h"
-#include "benchmark/benchmark.h"
+#include "benchmark/types.h"
namespace benchmark {
namespace {
diff --git a/src/string_util.h b/src/string_util.h
index 7a2ce0b..1a84666 100644
--- a/src/string_util.h
+++ b/src/string_util.h
@@ -6,7 +6,7 @@
#include <utility>
#include <vector>
-#include "benchmark/benchmark.h"
+#include "benchmark/counter.h"
#include "benchmark/export.h"
#include "check.h"
diff --git a/src/sysinfo.cc b/src/sysinfo.cc
index 3977772..12a09cf 100644
--- a/src/sysinfo.cc
+++ b/src/sysinfo.cc
@@ -77,7 +77,9 @@
#include <sstream>
#include <utility>
-#include "benchmark/benchmark.h"
+#include "benchmark/export.h"
+#include "benchmark/sysinfo.h"
+#include "benchmark/utils.h"
#include "check.h"
#include "cycleclock.h"
#include "log.h"
diff --git a/src/thread_manager.h b/src/thread_manager.h
index a0ac37a..80252b6 100644
--- a/src/thread_manager.h
+++ b/src/thread_manager.h
@@ -3,7 +3,9 @@
#include <atomic>
-#include "benchmark/benchmark.h"
+#include "benchmark/counter.h"
+#include "benchmark/statistics.h"
+#include "benchmark/types.h"
#include "mutex.h"
namespace benchmark {
diff --git a/test/args_product_test.cc b/test/args_product_test.cc
index 63b8b71..5dbcc21 100644
--- a/test/args_product_test.cc
+++ b/test/args_product_test.cc
@@ -3,7 +3,10 @@
#include <set>
#include <vector>
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/registration.h"
+#include "benchmark/state.h"
+#include "benchmark/utils.h"
class ArgsProductFixture : public ::benchmark::Fixture {
public:
diff --git a/test/basic_test.cc b/test/basic_test.cc
index 068cd98..e1db1cb 100644
--- a/test/basic_test.cc
+++ b/test/basic_test.cc
@@ -1,5 +1,8 @@
-#include "benchmark/benchmark.h"
+#include "benchmark/registration.h"
+#include "benchmark/state.h"
+#include "benchmark/types.h"
+#include "benchmark/utils.h"
#define BASIC_BENCHMARK_TEST(x) BENCHMARK(x)->Arg(8)->Arg(512)->Arg(8192)
diff --git a/test/benchmark_gtest.cc b/test/benchmark_gtest.cc
index 0aa2552..09d7c80 100644
--- a/test/benchmark_gtest.cc
+++ b/test/benchmark_gtest.cc
@@ -3,7 +3,7 @@
#include <vector>
#include "../src/benchmark_register.h"
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
@@ -136,7 +136,7 @@
}
TEST(AddCustomContext, Simple) {
- std::map<std::string, std::string> *&global_context = GetGlobalContext();
+ std::map<std::string, std::string>*& global_context = GetGlobalContext();
EXPECT_THAT(global_context, nullptr);
AddCustomContext("foo", "bar");
@@ -151,7 +151,7 @@
}
TEST(AddCustomContext, DuplicateKey) {
- std::map<std::string, std::string> *&global_context = GetGlobalContext();
+ std::map<std::string, std::string>*& global_context = GetGlobalContext();
EXPECT_THAT(global_context, nullptr);
AddCustomContext("foo", "bar");
diff --git a/test/benchmark_min_time_flag_iters_test.cc b/test/benchmark_min_time_flag_iters_test.cc
index dedcbe6..3866ac0 100644
--- a/test/benchmark_min_time_flag_iters_test.cc
+++ b/test/benchmark_min_time_flag_iters_test.cc
@@ -4,7 +4,10 @@
#include <string>
#include <vector>
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/registration.h"
+#include "benchmark/reporter.h"
+#include "benchmark/state.h"
// Tests that we can specify the number of iterations with
// --benchmark_min_time=<NUM>x.
diff --git a/test/benchmark_min_time_flag_time_test.cc b/test/benchmark_min_time_flag_time_test.cc
index bbc2cc3..2e8f52f 100644
--- a/test/benchmark_min_time_flag_time_test.cc
+++ b/test/benchmark_min_time_flag_time_test.cc
@@ -7,7 +7,10 @@
#include <string>
#include <vector>
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/registration.h"
+#include "benchmark/reporter.h"
+#include "benchmark/state.h"
// Tests that we can specify the min time with
// --benchmark_min_time=<NUM> (no suffix needed) OR
diff --git a/test/benchmark_name_gtest.cc b/test/benchmark_name_gtest.cc
index 0a6746d..34e97b0 100644
--- a/test/benchmark_name_gtest.cc
+++ b/test/benchmark_name_gtest.cc
@@ -1,4 +1,4 @@
-#include "benchmark/benchmark.h"
+#include "benchmark/reporter.h"
#include "gtest/gtest.h"
namespace {
diff --git a/test/benchmark_random_interleaving_gtest.cc b/test/benchmark_random_interleaving_gtest.cc
index 5f3a554..cb7f668 100644
--- a/test/benchmark_random_interleaving_gtest.cc
+++ b/test/benchmark_random_interleaving_gtest.cc
@@ -4,7 +4,10 @@
#include "../src/commandlineflags.h"
#include "../src/string_util.h"
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/registration.h"
+#include "benchmark/reporter.h"
+#include "benchmark/state.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
diff --git a/test/benchmark_setup_teardown_cb_types_gtest.cc b/test/benchmark_setup_teardown_cb_types_gtest.cc
index 2ed255d..716b722 100644
--- a/test/benchmark_setup_teardown_cb_types_gtest.cc
+++ b/test/benchmark_setup_teardown_cb_types_gtest.cc
@@ -1,4 +1,7 @@
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/reporter.h"
+#include "benchmark/state.h"
+#include "benchmark/types.h"
#include "gtest/gtest.h"
using benchmark::Benchmark;
diff --git a/test/benchmark_setup_teardown_test.cc b/test/benchmark_setup_teardown_test.cc
index eb45a73..52d2761 100644
--- a/test/benchmark_setup_teardown_test.cc
+++ b/test/benchmark_setup_teardown_test.cc
@@ -4,7 +4,9 @@
#include <cstring>
#include <string>
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/registration.h"
+#include "benchmark/state.h"
// Test that Setup() and Teardown() are called exactly once
// for each benchmark run (single-threaded).
diff --git a/test/benchmark_test.cc b/test/benchmark_test.cc
index 49cbfba..b98fbdf 100644
--- a/test/benchmark_test.cc
+++ b/test/benchmark_test.cc
@@ -1,5 +1,3 @@
-#include "benchmark/benchmark.h"
-
#include <assert.h>
#include <math.h>
#include <stdint.h>
@@ -19,6 +17,10 @@
#include <utility>
#include <vector>
+#include "benchmark/registration.h"
+#include "benchmark/state.h"
+#include "benchmark/utils.h"
+
#if defined(__GNUC__)
#define BENCHMARK_NOINLINE __attribute__((noinline))
#else
diff --git a/test/clobber_memory_assembly_test.cc b/test/clobber_memory_assembly_test.cc
index 54e26cc..24e0666 100644
--- a/test/clobber_memory_assembly_test.cc
+++ b/test/clobber_memory_assembly_test.cc
@@ -1,4 +1,5 @@
-#include <benchmark/benchmark.h>
+#include "benchmark/macros.h"
+#include "benchmark/utils.h"
#ifdef __clang__
#pragma clang diagnostic ignored "-Wreturn-type"
diff --git a/test/complexity_test.cc b/test/complexity_test.cc
index 8cf17f4..64a7e72 100644
--- a/test/complexity_test.cc
+++ b/test/complexity_test.cc
@@ -4,7 +4,12 @@
#include <cstdlib>
#include <vector>
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/registration.h"
+#include "benchmark/state.h"
+#include "benchmark/statistics.h"
+#include "benchmark/types.h"
+#include "benchmark/utils.h"
#include "output_test.h"
namespace {
diff --git a/test/cxx11_test.cc b/test/cxx11_test.cc
index db1a993..a2e8bc8 100644
--- a/test/cxx11_test.cc
+++ b/test/cxx11_test.cc
@@ -1,4 +1,4 @@
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
#if defined(_MSC_VER)
#if _MSVC_LANG != 201402L
diff --git a/test/diagnostics_test.cc b/test/diagnostics_test.cc
index e8d7d91..a79e49f 100644
--- a/test/diagnostics_test.cc
+++ b/test/diagnostics_test.cc
@@ -11,7 +11,10 @@
#include <stdexcept>
#include "../src/check.h"
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/registration.h"
+#include "benchmark/state.h"
+#include "benchmark/utils.h"
#if defined(__GNUC__) && !defined(__EXCEPTIONS)
#define TEST_HAS_NO_EXCEPTIONS
diff --git a/test/display_aggregates_only_test.cc b/test/display_aggregates_only_test.cc
index bae9759..86f202f 100644
--- a/test/display_aggregates_only_test.cc
+++ b/test/display_aggregates_only_test.cc
@@ -3,7 +3,9 @@
#include <cstdio>
#include <string>
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/registration.h"
+#include "benchmark/state.h"
#include "output_test.h"
// Ok this test is super ugly. We want to check what happens with the file
diff --git a/test/donotoptimize_assembly_test.cc b/test/donotoptimize_assembly_test.cc
index 1f817e0..d7b3b54 100644
--- a/test/donotoptimize_assembly_test.cc
+++ b/test/donotoptimize_assembly_test.cc
@@ -1,4 +1,5 @@
-#include <benchmark/benchmark.h>
+#include "benchmark/macros.h"
+#include "benchmark/utils.h"
#ifdef __clang__
#pragma clang diagnostic ignored "-Wreturn-type"
diff --git a/test/donotoptimize_test.cc b/test/donotoptimize_test.cc
index 7571cf4..34b1ed6 100644
--- a/test/donotoptimize_test.cc
+++ b/test/donotoptimize_test.cc
@@ -1,6 +1,7 @@
#include <cstdint>
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/utils.h"
namespace {
#if defined(__GNUC__)
diff --git a/test/filter_test.cc b/test/filter_test.cc
index 8c150eb..bcbf2ff 100644
--- a/test/filter_test.cc
+++ b/test/filter_test.cc
@@ -8,7 +8,10 @@
#include <sstream>
#include <string>
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/registration.h"
+#include "benchmark/reporter.h"
+#include "benchmark/state.h"
namespace {
diff --git a/test/fixture_test.cc b/test/fixture_test.cc
index d1093eb..8994dee 100644
--- a/test/fixture_test.cc
+++ b/test/fixture_test.cc
@@ -2,7 +2,9 @@
#include <cassert>
#include <memory>
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/registration.h"
+#include "benchmark/state.h"
#define FIXTURE_BECHMARK_NAME MyFixture
diff --git a/test/internal_threading_test.cc b/test/internal_threading_test.cc
index c57bf44..4d1dd1b 100644
--- a/test/internal_threading_test.cc
+++ b/test/internal_threading_test.cc
@@ -5,7 +5,10 @@
#include <thread>
#include "../src/timers.h"
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/counter.h"
+#include "benchmark/registration.h"
+#include "benchmark/state.h"
#include "output_test.h"
namespace {
diff --git a/test/link_main_test.cc b/test/link_main_test.cc
index 41dbac9..538f807 100644
--- a/test/link_main_test.cc
+++ b/test/link_main_test.cc
@@ -1,4 +1,6 @@
-#include "benchmark/benchmark.h"
+#include "benchmark/registration.h"
+#include "benchmark/state.h"
+#include "benchmark/utils.h"
namespace {
void BM_empty(benchmark::State& state) {
diff --git a/test/locale_impermeability_test.cc b/test/locale_impermeability_test.cc
index e2dd6cf..0776fe6 100644
--- a/test/locale_impermeability_test.cc
+++ b/test/locale_impermeability_test.cc
@@ -3,7 +3,9 @@
#include <cmath>
#include <cstdlib>
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/registration.h"
+#include "benchmark/state.h"
#include "output_test.h"
namespace {
diff --git a/test/manual_threading_test.cc b/test/manual_threading_test.cc
index b3252ec..bac36bc 100644
--- a/test/manual_threading_test.cc
+++ b/test/manual_threading_test.cc
@@ -6,7 +6,10 @@
#include <thread>
#include "../src/timers.h"
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/counter.h"
+#include "benchmark/registration.h"
+#include "benchmark/state.h"
namespace {
diff --git a/test/map_test.cc b/test/map_test.cc
index 018e12a..f4b41d2 100644
--- a/test/map_test.cc
+++ b/test/map_test.cc
@@ -1,7 +1,10 @@
#include <cstdlib>
#include <map>
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/registration.h"
+#include "benchmark/state.h"
+#include "benchmark/utils.h"
namespace {
diff --git a/test/memory_manager_test.cc b/test/memory_manager_test.cc
index 39b3216..36de9d4 100644
--- a/test/memory_manager_test.cc
+++ b/test/memory_manager_test.cc
@@ -1,6 +1,10 @@
#include <memory>
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/managers.h"
+#include "benchmark/registration.h"
+#include "benchmark/state.h"
+#include "benchmark/utils.h"
#include "output_test.h"
namespace {
diff --git a/test/memory_results_gtest.cc b/test/memory_results_gtest.cc
index 70a5a5a..f856fbf 100644
--- a/test/memory_results_gtest.cc
+++ b/test/memory_results_gtest.cc
@@ -1,6 +1,9 @@
#include <vector>
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/managers.h"
+#include "benchmark/reporter.h"
+#include "benchmark/state.h"
#include "gtest/gtest.h"
namespace {
diff --git a/test/multiple_ranges_test.cc b/test/multiple_ranges_test.cc
index 987b69c..695b52a 100644
--- a/test/multiple_ranges_test.cc
+++ b/test/multiple_ranges_test.cc
@@ -3,7 +3,10 @@
#include <set>
#include <vector>
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/registration.h"
+#include "benchmark/state.h"
+#include "benchmark/utils.h"
namespace {
class MultipleRangesFixture : public ::benchmark::Fixture {
diff --git a/test/options_test.cc b/test/options_test.cc
index 70e3e18..7ace933 100644
--- a/test/options_test.cc
+++ b/test/options_test.cc
@@ -1,7 +1,10 @@
#include <chrono>
#include <thread>
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/registration.h"
+#include "benchmark/state.h"
+#include "benchmark/types.h"
#if defined(NDEBUG)
#undef NDEBUG
diff --git a/test/output_test.h b/test/output_test.h
index 0fd557d..9337edc 100644
--- a/test/output_test.h
+++ b/test/output_test.h
@@ -11,7 +11,7 @@
#include <vector>
#include "../src/re.h"
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
#define CONCAT2(x, y) x##y
#define CONCAT(x, y) CONCAT2(x, y)
diff --git a/test/overload_test.cc b/test/overload_test.cc
index d1fee9a..0a62b78 100644
--- a/test/overload_test.cc
+++ b/test/overload_test.cc
@@ -1,4 +1,6 @@
-#include "benchmark/benchmark.h"
+#include "benchmark/macros.h"
+#include "benchmark/registration.h"
+#include "benchmark/state.h"
namespace {
// Simulate an overloaded function name.
diff --git a/test/perf_counters_test.cc b/test/perf_counters_test.cc
index a830b5e..d97fa37 100644
--- a/test/perf_counters_test.cc
+++ b/test/perf_counters_test.cc
@@ -3,7 +3,10 @@
#include "../src/commandlineflags.h"
#include "../src/perf_counters.h"
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/registration.h"
+#include "benchmark/state.h"
+#include "benchmark/utils.h"
#include "output_test.h"
namespace benchmark {
diff --git a/test/profiler_manager_gtest.cc b/test/profiler_manager_gtest.cc
index 434e4ec..6e83e32 100644
--- a/test/profiler_manager_gtest.cc
+++ b/test/profiler_manager_gtest.cc
@@ -1,6 +1,9 @@
#include <memory>
-#include "benchmark/benchmark.h"
+#include "benchmark/managers.h"
+#include "benchmark/registration.h"
+#include "benchmark/state.h"
+#include "benchmark/utils.h"
#include "gtest/gtest.h"
namespace {
diff --git a/test/profiler_manager_iterations_test.cc b/test/profiler_manager_iterations_test.cc
index c4983eb..90b34a1 100644
--- a/test/profiler_manager_iterations_test.cc
+++ b/test/profiler_manager_iterations_test.cc
@@ -3,7 +3,11 @@
#include <memory>
#include <vector>
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/managers.h"
+#include "benchmark/registration.h"
+#include "benchmark/reporter.h"
+#include "benchmark/state.h"
// Tests that we can specify the number of profiler iterations with
// --benchmark_min_time=<NUM>x.
diff --git a/test/profiler_manager_test.cc b/test/profiler_manager_test.cc
index 5c4b14d..bd86d42 100644
--- a/test/profiler_manager_test.cc
+++ b/test/profiler_manager_test.cc
@@ -3,7 +3,11 @@
#include <cassert>
#include <memory>
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/managers.h"
+#include "benchmark/registration.h"
+#include "benchmark/state.h"
+#include "benchmark/utils.h"
#include "output_test.h"
namespace {
diff --git a/test/register_benchmark_test.cc b/test/register_benchmark_test.cc
index 0ebd8f3..c662d49 100644
--- a/test/register_benchmark_test.cc
+++ b/test/register_benchmark_test.cc
@@ -4,7 +4,10 @@
#include <vector>
#include "../src/check.h" // NOTE: check.h is for internal use only!
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/registration.h"
+#include "benchmark/reporter.h"
+#include "benchmark/state.h"
namespace {
diff --git a/test/repetitions_test.cc b/test/repetitions_test.cc
index 9116fa6..80216ab 100644
--- a/test/repetitions_test.cc
+++ b/test/repetitions_test.cc
@@ -1,5 +1,7 @@
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/registration.h"
+#include "benchmark/state.h"
#include "output_test.h"
namespace {
diff --git a/test/report_aggregates_only_test.cc b/test/report_aggregates_only_test.cc
index 707d923..cb0ad09 100644
--- a/test/report_aggregates_only_test.cc
+++ b/test/report_aggregates_only_test.cc
@@ -3,7 +3,9 @@
#include <cstdio>
#include <string>
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/registration.h"
+#include "benchmark/state.h"
#include "output_test.h"
namespace {
diff --git a/test/reporter_output_test.cc b/test/reporter_output_test.cc
index 9940ab7..26d87de 100644
--- a/test/reporter_output_test.cc
+++ b/test/reporter_output_test.cc
@@ -1,6 +1,12 @@
#undef NDEBUG
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/registration.h"
+#include "benchmark/state.h"
+#include "benchmark/statistics.h"
+#include "benchmark/sysinfo.h"
+#include "benchmark/types.h"
+#include "benchmark/utils.h"
#include "output_test.h"
namespace {
diff --git a/test/skip_with_error_test.cc b/test/skip_with_error_test.cc
index 4258959..d30c23e 100644
--- a/test/skip_with_error_test.cc
+++ b/test/skip_with_error_test.cc
@@ -4,7 +4,11 @@
#include <vector>
#include "../src/check.h" // NOTE: check.h is for internal use only!
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/registration.h"
+#include "benchmark/reporter.h"
+#include "benchmark/state.h"
+#include "benchmark/utils.h"
namespace {
diff --git a/test/spec_arg_test.cc b/test/spec_arg_test.cc
index 21275ef..393eca5 100644
--- a/test/spec_arg_test.cc
+++ b/test/spec_arg_test.cc
@@ -8,7 +8,10 @@
#include <string>
#include <vector>
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/registration.h"
+#include "benchmark/reporter.h"
+#include "benchmark/state.h"
// Tests that we can override benchmark-spec value from FLAGS_benchmark_filter
// with argument to RunSpecifiedBenchmarks(...).
diff --git a/test/spec_arg_verbosity_test.cc b/test/spec_arg_verbosity_test.cc
index 318784c..49aadd9 100644
--- a/test/spec_arg_verbosity_test.cc
+++ b/test/spec_arg_verbosity_test.cc
@@ -2,7 +2,9 @@
#include <iostream>
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/registration.h"
+#include "benchmark/state.h"
namespace {
// Tests that the user specified verbosity level can be get.
diff --git a/test/state_assembly_test.cc b/test/state_assembly_test.cc
index e9ecfeb..5efceed 100644
--- a/test/state_assembly_test.cc
+++ b/test/state_assembly_test.cc
@@ -1,4 +1,5 @@
-#include <benchmark/benchmark.h>
+#include "benchmark/state.h"
+#include "benchmark/utils.h"
#ifdef __clang__
#pragma clang diagnostic ignored "-Wreturn-type"
diff --git a/test/templated_fixture_method_test.cc b/test/templated_fixture_method_test.cc
index 06fc7d8..3de726b 100644
--- a/test/templated_fixture_method_test.cc
+++ b/test/templated_fixture_method_test.cc
@@ -2,7 +2,9 @@
#include <cassert>
#include <memory>
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/registration.h"
+#include "benchmark/state.h"
template <typename T>
class MyFixture : public ::benchmark::Fixture {
diff --git a/test/templated_fixture_test.cc b/test/templated_fixture_test.cc
index af239c3..44108dd 100644
--- a/test/templated_fixture_test.cc
+++ b/test/templated_fixture_test.cc
@@ -2,7 +2,9 @@
#include <cassert>
#include <memory>
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/registration.h"
+#include "benchmark/state.h"
template <typename T>
class MyFixture : public ::benchmark::Fixture {
diff --git a/test/time_unit_gtest.cc b/test/time_unit_gtest.cc
index 0da1109..1d4d2d0 100644
--- a/test/time_unit_gtest.cc
+++ b/test/time_unit_gtest.cc
@@ -1,4 +1,5 @@
-#include "../include/benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/state.h"
#include "gtest/gtest.h"
namespace benchmark {
diff --git a/test/user_counters_tabular_test.cc b/test/user_counters_tabular_test.cc
index 7db0e20..f173f1b 100644
--- a/test/user_counters_tabular_test.cc
+++ b/test/user_counters_tabular_test.cc
@@ -1,7 +1,11 @@
#undef NDEBUG
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/counter.h"
+#include "benchmark/registration.h"
+#include "benchmark/state.h"
+#include "benchmark/utils.h"
#include "output_test.h"
namespace {
diff --git a/test/user_counters_test.cc b/test/user_counters_test.cc
index a8af087..9253d59 100644
--- a/test/user_counters_test.cc
+++ b/test/user_counters_test.cc
@@ -1,7 +1,11 @@
#undef NDEBUG
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/counter.h"
+#include "benchmark/registration.h"
+#include "benchmark/state.h"
+#include "benchmark/utils.h"
#include "output_test.h"
// ========================================================================= //
diff --git a/test/user_counters_thousands_test.cc b/test/user_counters_thousands_test.cc
index 0ef78d3..58170e9 100644
--- a/test/user_counters_thousands_test.cc
+++ b/test/user_counters_thousands_test.cc
@@ -1,7 +1,10 @@
#undef NDEBUG
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/counter.h"
+#include "benchmark/registration.h"
+#include "benchmark/state.h"
#include "output_test.h"
namespace {
diff --git a/test/user_counters_threads_test.cc b/test/user_counters_threads_test.cc
index e2e5ade..9fd01a6 100644
--- a/test/user_counters_threads_test.cc
+++ b/test/user_counters_threads_test.cc
@@ -1,7 +1,10 @@
#undef NDEBUG
-#include "benchmark/benchmark.h"
+#include "benchmark/benchmark_api.h"
+#include "benchmark/registration.h"
+#include "benchmark/state.h"
+#include "benchmark/utils.h"
#include "output_test.h"
// ========================================================================= //