1*4d6fc14bSjoerg // Copyright 2015 Google Inc. All rights reserved.
2*4d6fc14bSjoerg //
3*4d6fc14bSjoerg // Licensed under the Apache License, Version 2.0 (the "License");
4*4d6fc14bSjoerg // you may not use this file except in compliance with the License.
5*4d6fc14bSjoerg // You may obtain a copy of the License at
6*4d6fc14bSjoerg //
7*4d6fc14bSjoerg // http://www.apache.org/licenses/LICENSE-2.0
8*4d6fc14bSjoerg //
9*4d6fc14bSjoerg // Unless required by applicable law or agreed to in writing, software
10*4d6fc14bSjoerg // distributed under the License is distributed on an "AS IS" BASIS,
11*4d6fc14bSjoerg // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*4d6fc14bSjoerg // See the License for the specific language governing permissions and
13*4d6fc14bSjoerg // limitations under the License.
14*4d6fc14bSjoerg
15*4d6fc14bSjoerg // Support for registering benchmarks for functions.
16*4d6fc14bSjoerg
17*4d6fc14bSjoerg /* Example usage:
18*4d6fc14bSjoerg // Define a function that executes the code to be measured a
19*4d6fc14bSjoerg // specified number of times:
20*4d6fc14bSjoerg static void BM_StringCreation(benchmark::State& state) {
21*4d6fc14bSjoerg for (auto _ : state)
22*4d6fc14bSjoerg std::string empty_string;
23*4d6fc14bSjoerg }
24*4d6fc14bSjoerg
25*4d6fc14bSjoerg // Register the function as a benchmark
26*4d6fc14bSjoerg BENCHMARK(BM_StringCreation);
27*4d6fc14bSjoerg
28*4d6fc14bSjoerg // Define another benchmark
29*4d6fc14bSjoerg static void BM_StringCopy(benchmark::State& state) {
30*4d6fc14bSjoerg std::string x = "hello";
31*4d6fc14bSjoerg for (auto _ : state)
32*4d6fc14bSjoerg std::string copy(x);
33*4d6fc14bSjoerg }
34*4d6fc14bSjoerg BENCHMARK(BM_StringCopy);
35*4d6fc14bSjoerg
36*4d6fc14bSjoerg // Augment the main() program to invoke benchmarks if specified
37*4d6fc14bSjoerg // via the --benchmarks command line flag. E.g.,
38*4d6fc14bSjoerg // my_unittest --benchmark_filter=all
39*4d6fc14bSjoerg // my_unittest --benchmark_filter=BM_StringCreation
40*4d6fc14bSjoerg // my_unittest --benchmark_filter=String
41*4d6fc14bSjoerg // my_unittest --benchmark_filter='Copy|Creation'
42*4d6fc14bSjoerg int main(int argc, char** argv) {
43*4d6fc14bSjoerg benchmark::Initialize(&argc, argv);
44*4d6fc14bSjoerg benchmark::RunSpecifiedBenchmarks();
45*4d6fc14bSjoerg return 0;
46*4d6fc14bSjoerg }
47*4d6fc14bSjoerg
48*4d6fc14bSjoerg // Sometimes a family of microbenchmarks can be implemented with
49*4d6fc14bSjoerg // just one routine that takes an extra argument to specify which
50*4d6fc14bSjoerg // one of the family of benchmarks to run. For example, the following
51*4d6fc14bSjoerg // code defines a family of microbenchmarks for measuring the speed
52*4d6fc14bSjoerg // of memcpy() calls of different lengths:
53*4d6fc14bSjoerg
54*4d6fc14bSjoerg static void BM_memcpy(benchmark::State& state) {
55*4d6fc14bSjoerg char* src = new char[state.range(0)]; char* dst = new char[state.range(0)];
56*4d6fc14bSjoerg memset(src, 'x', state.range(0));
57*4d6fc14bSjoerg for (auto _ : state)
58*4d6fc14bSjoerg memcpy(dst, src, state.range(0));
59*4d6fc14bSjoerg state.SetBytesProcessed(int64_t(state.iterations()) *
60*4d6fc14bSjoerg int64_t(state.range(0)));
61*4d6fc14bSjoerg delete[] src; delete[] dst;
62*4d6fc14bSjoerg }
63*4d6fc14bSjoerg BENCHMARK(BM_memcpy)->Arg(8)->Arg(64)->Arg(512)->Arg(1<<10)->Arg(8<<10);
64*4d6fc14bSjoerg
65*4d6fc14bSjoerg // The preceding code is quite repetitive, and can be replaced with the
66*4d6fc14bSjoerg // following short-hand. The following invocation will pick a few
67*4d6fc14bSjoerg // appropriate arguments in the specified range and will generate a
68*4d6fc14bSjoerg // microbenchmark for each such argument.
69*4d6fc14bSjoerg BENCHMARK(BM_memcpy)->Range(8, 8<<10);
70*4d6fc14bSjoerg
71*4d6fc14bSjoerg // You might have a microbenchmark that depends on two inputs. For
72*4d6fc14bSjoerg // example, the following code defines a family of microbenchmarks for
73*4d6fc14bSjoerg // measuring the speed of set insertion.
74*4d6fc14bSjoerg static void BM_SetInsert(benchmark::State& state) {
75*4d6fc14bSjoerg set<int> data;
76*4d6fc14bSjoerg for (auto _ : state) {
77*4d6fc14bSjoerg state.PauseTiming();
78*4d6fc14bSjoerg data = ConstructRandomSet(state.range(0));
79*4d6fc14bSjoerg state.ResumeTiming();
80*4d6fc14bSjoerg for (int j = 0; j < state.range(1); ++j)
81*4d6fc14bSjoerg data.insert(RandomNumber());
82*4d6fc14bSjoerg }
83*4d6fc14bSjoerg }
84*4d6fc14bSjoerg BENCHMARK(BM_SetInsert)
85*4d6fc14bSjoerg ->Args({1<<10, 128})
86*4d6fc14bSjoerg ->Args({2<<10, 128})
87*4d6fc14bSjoerg ->Args({4<<10, 128})
88*4d6fc14bSjoerg ->Args({8<<10, 128})
89*4d6fc14bSjoerg ->Args({1<<10, 512})
90*4d6fc14bSjoerg ->Args({2<<10, 512})
91*4d6fc14bSjoerg ->Args({4<<10, 512})
92*4d6fc14bSjoerg ->Args({8<<10, 512});
93*4d6fc14bSjoerg
94*4d6fc14bSjoerg // The preceding code is quite repetitive, and can be replaced with
95*4d6fc14bSjoerg // the following short-hand. The following macro will pick a few
96*4d6fc14bSjoerg // appropriate arguments in the product of the two specified ranges
97*4d6fc14bSjoerg // and will generate a microbenchmark for each such pair.
98*4d6fc14bSjoerg BENCHMARK(BM_SetInsert)->Ranges({{1<<10, 8<<10}, {128, 512}});
99*4d6fc14bSjoerg
100*4d6fc14bSjoerg // For more complex patterns of inputs, passing a custom function
101*4d6fc14bSjoerg // to Apply allows programmatic specification of an
102*4d6fc14bSjoerg // arbitrary set of arguments to run the microbenchmark on.
103*4d6fc14bSjoerg // The following example enumerates a dense range on
104*4d6fc14bSjoerg // one parameter, and a sparse range on the second.
105*4d6fc14bSjoerg static void CustomArguments(benchmark::internal::Benchmark* b) {
106*4d6fc14bSjoerg for (int i = 0; i <= 10; ++i)
107*4d6fc14bSjoerg for (int j = 32; j <= 1024*1024; j *= 8)
108*4d6fc14bSjoerg b->Args({i, j});
109*4d6fc14bSjoerg }
110*4d6fc14bSjoerg BENCHMARK(BM_SetInsert)->Apply(CustomArguments);
111*4d6fc14bSjoerg
112*4d6fc14bSjoerg // Templated microbenchmarks work the same way:
113*4d6fc14bSjoerg // Produce then consume 'size' messages 'iters' times
114*4d6fc14bSjoerg // Measures throughput in the absence of multiprogramming.
115*4d6fc14bSjoerg template <class Q> int BM_Sequential(benchmark::State& state) {
116*4d6fc14bSjoerg Q q;
117*4d6fc14bSjoerg typename Q::value_type v;
118*4d6fc14bSjoerg for (auto _ : state) {
119*4d6fc14bSjoerg for (int i = state.range(0); i--; )
120*4d6fc14bSjoerg q.push(v);
121*4d6fc14bSjoerg for (int e = state.range(0); e--; )
122*4d6fc14bSjoerg q.Wait(&v);
123*4d6fc14bSjoerg }
124*4d6fc14bSjoerg // actually messages, not bytes:
125*4d6fc14bSjoerg state.SetBytesProcessed(
126*4d6fc14bSjoerg static_cast<int64_t>(state.iterations())*state.range(0));
127*4d6fc14bSjoerg }
128*4d6fc14bSjoerg BENCHMARK_TEMPLATE(BM_Sequential, WaitQueue<int>)->Range(1<<0, 1<<10);
129*4d6fc14bSjoerg
130*4d6fc14bSjoerg Use `Benchmark::MinTime(double t)` to set the minimum time used to run the
131*4d6fc14bSjoerg benchmark. This option overrides the `benchmark_min_time` flag.
132*4d6fc14bSjoerg
133*4d6fc14bSjoerg void BM_test(benchmark::State& state) {
134*4d6fc14bSjoerg ... body ...
135*4d6fc14bSjoerg }
136*4d6fc14bSjoerg BENCHMARK(BM_test)->MinTime(2.0); // Run for at least 2 seconds.
137*4d6fc14bSjoerg
138*4d6fc14bSjoerg In a multithreaded test, it is guaranteed that none of the threads will start
139*4d6fc14bSjoerg until all have reached the loop start, and all will have finished before any
140*4d6fc14bSjoerg thread exits the loop body. As such, any global setup or teardown you want to
141*4d6fc14bSjoerg do can be wrapped in a check against the thread index:
142*4d6fc14bSjoerg
143*4d6fc14bSjoerg static void BM_MultiThreaded(benchmark::State& state) {
144*4d6fc14bSjoerg if (state.thread_index == 0) {
145*4d6fc14bSjoerg // Setup code here.
146*4d6fc14bSjoerg }
147*4d6fc14bSjoerg for (auto _ : state) {
148*4d6fc14bSjoerg // Run the test as normal.
149*4d6fc14bSjoerg }
150*4d6fc14bSjoerg if (state.thread_index == 0) {
151*4d6fc14bSjoerg // Teardown code here.
152*4d6fc14bSjoerg }
153*4d6fc14bSjoerg }
154*4d6fc14bSjoerg BENCHMARK(BM_MultiThreaded)->Threads(4);
155*4d6fc14bSjoerg
156*4d6fc14bSjoerg
157*4d6fc14bSjoerg If a benchmark runs a few milliseconds it may be hard to visually compare the
158*4d6fc14bSjoerg measured times, since the output data is given in nanoseconds per default. In
159*4d6fc14bSjoerg order to manually set the time unit, you can specify it manually:
160*4d6fc14bSjoerg
161*4d6fc14bSjoerg BENCHMARK(BM_test)->Unit(benchmark::kMillisecond);
162*4d6fc14bSjoerg */
163*4d6fc14bSjoerg
164*4d6fc14bSjoerg #ifndef BENCHMARK_BENCHMARK_H_
165*4d6fc14bSjoerg #define BENCHMARK_BENCHMARK_H_
166*4d6fc14bSjoerg
167*4d6fc14bSjoerg // The _MSVC_LANG check should detect Visual Studio 2015 Update 3 and newer.
168*4d6fc14bSjoerg #if __cplusplus >= 201103L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201103L)
169*4d6fc14bSjoerg #define BENCHMARK_HAS_CXX11
170*4d6fc14bSjoerg #endif
171*4d6fc14bSjoerg
172*4d6fc14bSjoerg #include <stdint.h>
173*4d6fc14bSjoerg
174*4d6fc14bSjoerg #include <algorithm>
175*4d6fc14bSjoerg #include <cassert>
176*4d6fc14bSjoerg #include <cstddef>
177*4d6fc14bSjoerg #include <iosfwd>
178*4d6fc14bSjoerg #include <map>
179*4d6fc14bSjoerg #include <set>
180*4d6fc14bSjoerg #include <string>
181*4d6fc14bSjoerg #include <vector>
182*4d6fc14bSjoerg
183*4d6fc14bSjoerg #if defined(BENCHMARK_HAS_CXX11)
184*4d6fc14bSjoerg #include <initializer_list>
185*4d6fc14bSjoerg #include <type_traits>
186*4d6fc14bSjoerg #include <utility>
187*4d6fc14bSjoerg #endif
188*4d6fc14bSjoerg
189*4d6fc14bSjoerg #if defined(_MSC_VER)
190*4d6fc14bSjoerg #include <intrin.h> // for _ReadWriteBarrier
191*4d6fc14bSjoerg #endif
192*4d6fc14bSjoerg
193*4d6fc14bSjoerg #ifndef BENCHMARK_HAS_CXX11
194*4d6fc14bSjoerg #define BENCHMARK_DISALLOW_COPY_AND_ASSIGN(TypeName) \
195*4d6fc14bSjoerg TypeName(const TypeName&); \
196*4d6fc14bSjoerg TypeName& operator=(const TypeName&)
197*4d6fc14bSjoerg #else
198*4d6fc14bSjoerg #define BENCHMARK_DISALLOW_COPY_AND_ASSIGN(TypeName) \
199*4d6fc14bSjoerg TypeName(const TypeName&) = delete; \
200*4d6fc14bSjoerg TypeName& operator=(const TypeName&) = delete
201*4d6fc14bSjoerg #endif
202*4d6fc14bSjoerg
203*4d6fc14bSjoerg #if defined(__GNUC__)
204*4d6fc14bSjoerg #define BENCHMARK_UNUSED __attribute__((unused))
205*4d6fc14bSjoerg #define BENCHMARK_ALWAYS_INLINE __attribute__((always_inline))
206*4d6fc14bSjoerg #define BENCHMARK_NOEXCEPT noexcept
207*4d6fc14bSjoerg #define BENCHMARK_NOEXCEPT_OP(x) noexcept(x)
208*4d6fc14bSjoerg #elif defined(_MSC_VER) && !defined(__clang__)
209*4d6fc14bSjoerg #define BENCHMARK_UNUSED
210*4d6fc14bSjoerg #define BENCHMARK_ALWAYS_INLINE __forceinline
211*4d6fc14bSjoerg #if _MSC_VER >= 1900
212*4d6fc14bSjoerg #define BENCHMARK_NOEXCEPT noexcept
213*4d6fc14bSjoerg #define BENCHMARK_NOEXCEPT_OP(x) noexcept(x)
214*4d6fc14bSjoerg #else
215*4d6fc14bSjoerg #define BENCHMARK_NOEXCEPT
216*4d6fc14bSjoerg #define BENCHMARK_NOEXCEPT_OP(x)
217*4d6fc14bSjoerg #endif
218*4d6fc14bSjoerg #define __func__ __FUNCTION__
219*4d6fc14bSjoerg #else
220*4d6fc14bSjoerg #define BENCHMARK_UNUSED
221*4d6fc14bSjoerg #define BENCHMARK_ALWAYS_INLINE
222*4d6fc14bSjoerg #define BENCHMARK_NOEXCEPT
223*4d6fc14bSjoerg #define BENCHMARK_NOEXCEPT_OP(x)
224*4d6fc14bSjoerg #endif
225*4d6fc14bSjoerg
226*4d6fc14bSjoerg #define BENCHMARK_INTERNAL_TOSTRING2(x) #x
227*4d6fc14bSjoerg #define BENCHMARK_INTERNAL_TOSTRING(x) BENCHMARK_INTERNAL_TOSTRING2(x)
228*4d6fc14bSjoerg
229*4d6fc14bSjoerg #if defined(__GNUC__) || defined(__clang__)
230*4d6fc14bSjoerg #define BENCHMARK_BUILTIN_EXPECT(x, y) __builtin_expect(x, y)
231*4d6fc14bSjoerg #define BENCHMARK_DEPRECATED_MSG(msg) __attribute__((deprecated(msg)))
232*4d6fc14bSjoerg #else
233*4d6fc14bSjoerg #define BENCHMARK_BUILTIN_EXPECT(x, y) x
234*4d6fc14bSjoerg #define BENCHMARK_DEPRECATED_MSG(msg)
235*4d6fc14bSjoerg #define BENCHMARK_WARNING_MSG(msg) \
236*4d6fc14bSjoerg __pragma(message(__FILE__ "(" BENCHMARK_INTERNAL_TOSTRING( \
237*4d6fc14bSjoerg __LINE__) ") : warning note: " msg))
238*4d6fc14bSjoerg #endif
239*4d6fc14bSjoerg
240*4d6fc14bSjoerg #if defined(__GNUC__) && !defined(__clang__)
241*4d6fc14bSjoerg #define BENCHMARK_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
242*4d6fc14bSjoerg #endif
243*4d6fc14bSjoerg
244*4d6fc14bSjoerg #ifndef __has_builtin
245*4d6fc14bSjoerg #define __has_builtin(x) 0
246*4d6fc14bSjoerg #endif
247*4d6fc14bSjoerg
248*4d6fc14bSjoerg #if defined(__GNUC__) || __has_builtin(__builtin_unreachable)
249*4d6fc14bSjoerg #define BENCHMARK_UNREACHABLE() __builtin_unreachable()
250*4d6fc14bSjoerg #elif defined(_MSC_VER)
251*4d6fc14bSjoerg #define BENCHMARK_UNREACHABLE() __assume(false)
252*4d6fc14bSjoerg #else
253*4d6fc14bSjoerg #define BENCHMARK_UNREACHABLE() ((void)0)
254*4d6fc14bSjoerg #endif
255*4d6fc14bSjoerg
256*4d6fc14bSjoerg namespace benchmark {
257*4d6fc14bSjoerg class BenchmarkReporter;
258*4d6fc14bSjoerg class MemoryManager;
259*4d6fc14bSjoerg
260*4d6fc14bSjoerg void Initialize(int* argc, char** argv);
261*4d6fc14bSjoerg
262*4d6fc14bSjoerg // Report to stdout all arguments in 'argv' as unrecognized except the first.
263*4d6fc14bSjoerg // Returns true there is at least on unrecognized argument (i.e. 'argc' > 1).
264*4d6fc14bSjoerg bool ReportUnrecognizedArguments(int argc, char** argv);
265*4d6fc14bSjoerg
266*4d6fc14bSjoerg // Generate a list of benchmarks matching the specified --benchmark_filter flag
267*4d6fc14bSjoerg // and if --benchmark_list_tests is specified return after printing the name
268*4d6fc14bSjoerg // of each matching benchmark. Otherwise run each matching benchmark and
269*4d6fc14bSjoerg // report the results.
270*4d6fc14bSjoerg //
271*4d6fc14bSjoerg // The second and third overload use the specified 'display_reporter' and
272*4d6fc14bSjoerg // 'file_reporter' respectively. 'file_reporter' will write to the file
273*4d6fc14bSjoerg // specified
274*4d6fc14bSjoerg // by '--benchmark_output'. If '--benchmark_output' is not given the
275*4d6fc14bSjoerg // 'file_reporter' is ignored.
276*4d6fc14bSjoerg //
277*4d6fc14bSjoerg // RETURNS: The number of matching benchmarks.
278*4d6fc14bSjoerg size_t RunSpecifiedBenchmarks();
279*4d6fc14bSjoerg size_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter);
280*4d6fc14bSjoerg size_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter,
281*4d6fc14bSjoerg BenchmarkReporter* file_reporter);
282*4d6fc14bSjoerg
283*4d6fc14bSjoerg // Register a MemoryManager instance that will be used to collect and report
284*4d6fc14bSjoerg // allocation measurements for benchmark runs.
285*4d6fc14bSjoerg void RegisterMemoryManager(MemoryManager* memory_manager);
286*4d6fc14bSjoerg
287*4d6fc14bSjoerg namespace internal {
288*4d6fc14bSjoerg class Benchmark;
289*4d6fc14bSjoerg class BenchmarkImp;
290*4d6fc14bSjoerg class BenchmarkFamilies;
291*4d6fc14bSjoerg
292*4d6fc14bSjoerg void UseCharPointer(char const volatile*);
293*4d6fc14bSjoerg
294*4d6fc14bSjoerg // Take ownership of the pointer and register the benchmark. Return the
295*4d6fc14bSjoerg // registered benchmark.
296*4d6fc14bSjoerg Benchmark* RegisterBenchmarkInternal(Benchmark*);
297*4d6fc14bSjoerg
298*4d6fc14bSjoerg // Ensure that the standard streams are properly initialized in every TU.
299*4d6fc14bSjoerg int InitializeStreams();
300*4d6fc14bSjoerg BENCHMARK_UNUSED static int stream_init_anchor = InitializeStreams();
301*4d6fc14bSjoerg
302*4d6fc14bSjoerg } // namespace internal
303*4d6fc14bSjoerg
304*4d6fc14bSjoerg #if (!defined(__GNUC__) && !defined(__clang__)) || defined(__pnacl__) || \
305*4d6fc14bSjoerg defined(__EMSCRIPTEN__)
306*4d6fc14bSjoerg #define BENCHMARK_HAS_NO_INLINE_ASSEMBLY
307*4d6fc14bSjoerg #endif
308*4d6fc14bSjoerg
309*4d6fc14bSjoerg // The DoNotOptimize(...) function can be used to prevent a value or
310*4d6fc14bSjoerg // expression from being optimized away by the compiler. This function is
311*4d6fc14bSjoerg // intended to add little to no overhead.
312*4d6fc14bSjoerg // See: https://youtu.be/nXaxk27zwlk?t=2441
313*4d6fc14bSjoerg #ifndef BENCHMARK_HAS_NO_INLINE_ASSEMBLY
314*4d6fc14bSjoerg template <class Tp>
DoNotOptimize(Tp const & value)315*4d6fc14bSjoerg inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) {
316*4d6fc14bSjoerg asm volatile("" : : "r,m"(value) : "memory");
317*4d6fc14bSjoerg }
318*4d6fc14bSjoerg
319*4d6fc14bSjoerg template <class Tp>
DoNotOptimize(Tp & value)320*4d6fc14bSjoerg inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp& value) {
321*4d6fc14bSjoerg #if defined(__clang__)
322*4d6fc14bSjoerg asm volatile("" : "+r,m"(value) : : "memory");
323*4d6fc14bSjoerg #else
324*4d6fc14bSjoerg asm volatile("" : "+m,r"(value) : : "memory");
325*4d6fc14bSjoerg #endif
326*4d6fc14bSjoerg }
327*4d6fc14bSjoerg
328*4d6fc14bSjoerg // Force the compiler to flush pending writes to global memory. Acts as an
329*4d6fc14bSjoerg // effective read/write barrier
ClobberMemory()330*4d6fc14bSjoerg inline BENCHMARK_ALWAYS_INLINE void ClobberMemory() {
331*4d6fc14bSjoerg asm volatile("" : : : "memory");
332*4d6fc14bSjoerg }
333*4d6fc14bSjoerg #elif defined(_MSC_VER)
334*4d6fc14bSjoerg template <class Tp>
DoNotOptimize(Tp const & value)335*4d6fc14bSjoerg inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) {
336*4d6fc14bSjoerg internal::UseCharPointer(&reinterpret_cast<char const volatile&>(value));
337*4d6fc14bSjoerg _ReadWriteBarrier();
338*4d6fc14bSjoerg }
339*4d6fc14bSjoerg
ClobberMemory()340*4d6fc14bSjoerg inline BENCHMARK_ALWAYS_INLINE void ClobberMemory() { _ReadWriteBarrier(); }
341*4d6fc14bSjoerg #else
342*4d6fc14bSjoerg template <class Tp>
DoNotOptimize(Tp const & value)343*4d6fc14bSjoerg inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) {
344*4d6fc14bSjoerg internal::UseCharPointer(&reinterpret_cast<char const volatile&>(value));
345*4d6fc14bSjoerg }
346*4d6fc14bSjoerg // FIXME Add ClobberMemory() for non-gnu and non-msvc compilers
347*4d6fc14bSjoerg #endif
348*4d6fc14bSjoerg
349*4d6fc14bSjoerg // This class is used for user-defined counters.
350*4d6fc14bSjoerg class Counter {
351*4d6fc14bSjoerg public:
352*4d6fc14bSjoerg enum Flags {
353*4d6fc14bSjoerg kDefaults = 0,
354*4d6fc14bSjoerg // Mark the counter as a rate. It will be presented divided
355*4d6fc14bSjoerg // by the duration of the benchmark.
356*4d6fc14bSjoerg kIsRate = 1U << 0U,
357*4d6fc14bSjoerg // Mark the counter as a thread-average quantity. It will be
358*4d6fc14bSjoerg // presented divided by the number of threads.
359*4d6fc14bSjoerg kAvgThreads = 1U << 1U,
360*4d6fc14bSjoerg // Mark the counter as a thread-average rate. See above.
361*4d6fc14bSjoerg kAvgThreadsRate = kIsRate | kAvgThreads,
362*4d6fc14bSjoerg // Mark the counter as a constant value, valid/same for *every* iteration.
363*4d6fc14bSjoerg // When reporting, it will be *multiplied* by the iteration count.
364*4d6fc14bSjoerg kIsIterationInvariant = 1U << 2U,
365*4d6fc14bSjoerg // Mark the counter as a constant rate.
366*4d6fc14bSjoerg // When reporting, it will be *multiplied* by the iteration count
367*4d6fc14bSjoerg // and then divided by the duration of the benchmark.
368*4d6fc14bSjoerg kIsIterationInvariantRate = kIsRate | kIsIterationInvariant,
369*4d6fc14bSjoerg // Mark the counter as a iteration-average quantity.
370*4d6fc14bSjoerg // It will be presented divided by the number of iterations.
371*4d6fc14bSjoerg kAvgIterations = 1U << 3U,
372*4d6fc14bSjoerg // Mark the counter as a iteration-average rate. See above.
373*4d6fc14bSjoerg kAvgIterationsRate = kIsRate | kAvgIterations
374*4d6fc14bSjoerg };
375*4d6fc14bSjoerg
376*4d6fc14bSjoerg enum OneK {
377*4d6fc14bSjoerg // 1'000 items per 1k
378*4d6fc14bSjoerg kIs1000 = 1000,
379*4d6fc14bSjoerg // 1'024 items per 1k
380*4d6fc14bSjoerg kIs1024 = 1024
381*4d6fc14bSjoerg };
382*4d6fc14bSjoerg
383*4d6fc14bSjoerg double value;
384*4d6fc14bSjoerg Flags flags;
385*4d6fc14bSjoerg OneK oneK;
386*4d6fc14bSjoerg
387*4d6fc14bSjoerg BENCHMARK_ALWAYS_INLINE
388*4d6fc14bSjoerg Counter(double v = 0., Flags f = kDefaults, OneK k = kIs1000)
value(v)389*4d6fc14bSjoerg : value(v), flags(f), oneK(k) {}
390*4d6fc14bSjoerg
391*4d6fc14bSjoerg BENCHMARK_ALWAYS_INLINE operator double const&() const { return value; }
392*4d6fc14bSjoerg BENCHMARK_ALWAYS_INLINE operator double&() { return value; }
393*4d6fc14bSjoerg };
394*4d6fc14bSjoerg
395*4d6fc14bSjoerg // A helper for user code to create unforeseen combinations of Flags, without
396*4d6fc14bSjoerg // having to do this cast manually each time, or providing this operator.
397*4d6fc14bSjoerg Counter::Flags inline operator|(const Counter::Flags& LHS,
398*4d6fc14bSjoerg const Counter::Flags& RHS) {
399*4d6fc14bSjoerg return static_cast<Counter::Flags>(static_cast<int>(LHS) |
400*4d6fc14bSjoerg static_cast<int>(RHS));
401*4d6fc14bSjoerg }
402*4d6fc14bSjoerg
403*4d6fc14bSjoerg // This is the container for the user-defined counters.
404*4d6fc14bSjoerg typedef std::map<std::string, Counter> UserCounters;
405*4d6fc14bSjoerg
406*4d6fc14bSjoerg // TimeUnit is passed to a benchmark in order to specify the order of magnitude
407*4d6fc14bSjoerg // for the measured time.
408*4d6fc14bSjoerg enum TimeUnit { kNanosecond, kMicrosecond, kMillisecond };
409*4d6fc14bSjoerg
410*4d6fc14bSjoerg // BigO is passed to a benchmark in order to specify the asymptotic
411*4d6fc14bSjoerg // computational
412*4d6fc14bSjoerg // complexity for the benchmark. In case oAuto is selected, complexity will be
413*4d6fc14bSjoerg // calculated automatically to the best fit.
414*4d6fc14bSjoerg enum BigO { oNone, o1, oN, oNSquared, oNCubed, oLogN, oNLogN, oAuto, oLambda };
415*4d6fc14bSjoerg
416*4d6fc14bSjoerg // BigOFunc is passed to a benchmark in order to specify the asymptotic
417*4d6fc14bSjoerg // computational complexity for the benchmark.
418*4d6fc14bSjoerg typedef double(BigOFunc)(int64_t);
419*4d6fc14bSjoerg
420*4d6fc14bSjoerg // StatisticsFunc is passed to a benchmark in order to compute some descriptive
421*4d6fc14bSjoerg // statistics over all the measurements of some type
422*4d6fc14bSjoerg typedef double(StatisticsFunc)(const std::vector<double>&);
423*4d6fc14bSjoerg
424*4d6fc14bSjoerg struct Statistics {
425*4d6fc14bSjoerg std::string name_;
426*4d6fc14bSjoerg StatisticsFunc* compute_;
427*4d6fc14bSjoerg
StatisticsStatistics428*4d6fc14bSjoerg Statistics(const std::string& name, StatisticsFunc* compute)
429*4d6fc14bSjoerg : name_(name), compute_(compute) {}
430*4d6fc14bSjoerg };
431*4d6fc14bSjoerg
432*4d6fc14bSjoerg namespace internal {
433*4d6fc14bSjoerg struct BenchmarkInstance;
434*4d6fc14bSjoerg class ThreadTimer;
435*4d6fc14bSjoerg class ThreadManager;
436*4d6fc14bSjoerg
437*4d6fc14bSjoerg enum AggregationReportMode
438*4d6fc14bSjoerg #if defined(BENCHMARK_HAS_CXX11)
439*4d6fc14bSjoerg : unsigned
440*4d6fc14bSjoerg #else
441*4d6fc14bSjoerg #endif
442*4d6fc14bSjoerg {
443*4d6fc14bSjoerg // The mode has not been manually specified
444*4d6fc14bSjoerg ARM_Unspecified = 0,
445*4d6fc14bSjoerg // The mode is user-specified.
446*4d6fc14bSjoerg // This may or may not be set when the following bit-flags are set.
447*4d6fc14bSjoerg ARM_Default = 1U << 0U,
448*4d6fc14bSjoerg // File reporter should only output aggregates.
449*4d6fc14bSjoerg ARM_FileReportAggregatesOnly = 1U << 1U,
450*4d6fc14bSjoerg // Display reporter should only output aggregates
451*4d6fc14bSjoerg ARM_DisplayReportAggregatesOnly = 1U << 2U,
452*4d6fc14bSjoerg // Both reporters should only display aggregates.
453*4d6fc14bSjoerg ARM_ReportAggregatesOnly =
454*4d6fc14bSjoerg ARM_FileReportAggregatesOnly | ARM_DisplayReportAggregatesOnly
455*4d6fc14bSjoerg };
456*4d6fc14bSjoerg
457*4d6fc14bSjoerg } // namespace internal
458*4d6fc14bSjoerg
459*4d6fc14bSjoerg // State is passed to a running Benchmark and contains state for the
460*4d6fc14bSjoerg // benchmark to use.
461*4d6fc14bSjoerg class State {
462*4d6fc14bSjoerg public:
463*4d6fc14bSjoerg struct StateIterator;
464*4d6fc14bSjoerg friend struct StateIterator;
465*4d6fc14bSjoerg
466*4d6fc14bSjoerg // Returns iterators used to run each iteration of a benchmark using a
467*4d6fc14bSjoerg // C++11 ranged-based for loop. These functions should not be called directly.
468*4d6fc14bSjoerg //
469*4d6fc14bSjoerg // REQUIRES: The benchmark has not started running yet. Neither begin nor end
470*4d6fc14bSjoerg // have been called previously.
471*4d6fc14bSjoerg //
472*4d6fc14bSjoerg // NOTE: KeepRunning may not be used after calling either of these functions.
473*4d6fc14bSjoerg BENCHMARK_ALWAYS_INLINE StateIterator begin();
474*4d6fc14bSjoerg BENCHMARK_ALWAYS_INLINE StateIterator end();
475*4d6fc14bSjoerg
476*4d6fc14bSjoerg // Returns true if the benchmark should continue through another iteration.
477*4d6fc14bSjoerg // NOTE: A benchmark may not return from the test until KeepRunning() has
478*4d6fc14bSjoerg // returned false.
479*4d6fc14bSjoerg bool KeepRunning();
480*4d6fc14bSjoerg
481*4d6fc14bSjoerg // Returns true iff the benchmark should run n more iterations.
482*4d6fc14bSjoerg // REQUIRES: 'n' > 0.
483*4d6fc14bSjoerg // NOTE: A benchmark must not return from the test until KeepRunningBatch()
484*4d6fc14bSjoerg // has returned false.
485*4d6fc14bSjoerg // NOTE: KeepRunningBatch() may overshoot by up to 'n' iterations.
486*4d6fc14bSjoerg //
487*4d6fc14bSjoerg // Intended usage:
488*4d6fc14bSjoerg // while (state.KeepRunningBatch(1000)) {
489*4d6fc14bSjoerg // // process 1000 elements
490*4d6fc14bSjoerg // }
491*4d6fc14bSjoerg bool KeepRunningBatch(size_t n);
492*4d6fc14bSjoerg
493*4d6fc14bSjoerg // REQUIRES: timer is running and 'SkipWithError(...)' has not been called
494*4d6fc14bSjoerg // by the current thread.
495*4d6fc14bSjoerg // Stop the benchmark timer. If not called, the timer will be
496*4d6fc14bSjoerg // automatically stopped after the last iteration of the benchmark loop.
497*4d6fc14bSjoerg //
498*4d6fc14bSjoerg // For threaded benchmarks the PauseTiming() function only pauses the timing
499*4d6fc14bSjoerg // for the current thread.
500*4d6fc14bSjoerg //
501*4d6fc14bSjoerg // NOTE: The "real time" measurement is per-thread. If different threads
502*4d6fc14bSjoerg // report different measurements the largest one is reported.
503*4d6fc14bSjoerg //
504*4d6fc14bSjoerg // NOTE: PauseTiming()/ResumeTiming() are relatively
505*4d6fc14bSjoerg // heavyweight, and so their use should generally be avoided
506*4d6fc14bSjoerg // within each benchmark iteration, if possible.
507*4d6fc14bSjoerg void PauseTiming();
508*4d6fc14bSjoerg
509*4d6fc14bSjoerg // REQUIRES: timer is not running and 'SkipWithError(...)' has not been called
510*4d6fc14bSjoerg // by the current thread.
511*4d6fc14bSjoerg // Start the benchmark timer. The timer is NOT running on entrance to the
512*4d6fc14bSjoerg // benchmark function. It begins running after control flow enters the
513*4d6fc14bSjoerg // benchmark loop.
514*4d6fc14bSjoerg //
515*4d6fc14bSjoerg // NOTE: PauseTiming()/ResumeTiming() are relatively
516*4d6fc14bSjoerg // heavyweight, and so their use should generally be avoided
517*4d6fc14bSjoerg // within each benchmark iteration, if possible.
518*4d6fc14bSjoerg void ResumeTiming();
519*4d6fc14bSjoerg
520*4d6fc14bSjoerg // REQUIRES: 'SkipWithError(...)' has not been called previously by the
521*4d6fc14bSjoerg // current thread.
522*4d6fc14bSjoerg // Report the benchmark as resulting in an error with the specified 'msg'.
523*4d6fc14bSjoerg // After this call the user may explicitly 'return' from the benchmark.
524*4d6fc14bSjoerg //
525*4d6fc14bSjoerg // If the ranged-for style of benchmark loop is used, the user must explicitly
526*4d6fc14bSjoerg // break from the loop, otherwise all future iterations will be run.
527*4d6fc14bSjoerg // If the 'KeepRunning()' loop is used the current thread will automatically
528*4d6fc14bSjoerg // exit the loop at the end of the current iteration.
529*4d6fc14bSjoerg //
530*4d6fc14bSjoerg // For threaded benchmarks only the current thread stops executing and future
531*4d6fc14bSjoerg // calls to `KeepRunning()` will block until all threads have completed
532*4d6fc14bSjoerg // the `KeepRunning()` loop. If multiple threads report an error only the
533*4d6fc14bSjoerg // first error message is used.
534*4d6fc14bSjoerg //
535*4d6fc14bSjoerg // NOTE: Calling 'SkipWithError(...)' does not cause the benchmark to exit
536*4d6fc14bSjoerg // the current scope immediately. If the function is called from within
537*4d6fc14bSjoerg // the 'KeepRunning()' loop the current iteration will finish. It is the users
538*4d6fc14bSjoerg // responsibility to exit the scope as needed.
539*4d6fc14bSjoerg void SkipWithError(const char* msg);
540*4d6fc14bSjoerg
541*4d6fc14bSjoerg // REQUIRES: called exactly once per iteration of the benchmarking loop.
542*4d6fc14bSjoerg // Set the manually measured time for this benchmark iteration, which
543*4d6fc14bSjoerg // is used instead of automatically measured time if UseManualTime() was
544*4d6fc14bSjoerg // specified.
545*4d6fc14bSjoerg //
546*4d6fc14bSjoerg // For threaded benchmarks the final value will be set to the largest
547*4d6fc14bSjoerg // reported values.
548*4d6fc14bSjoerg void SetIterationTime(double seconds);
549*4d6fc14bSjoerg
550*4d6fc14bSjoerg // Set the number of bytes processed by the current benchmark
551*4d6fc14bSjoerg // execution. This routine is typically called once at the end of a
552*4d6fc14bSjoerg // throughput oriented benchmark.
553*4d6fc14bSjoerg //
554*4d6fc14bSjoerg // REQUIRES: a benchmark has exited its benchmarking loop.
555*4d6fc14bSjoerg BENCHMARK_ALWAYS_INLINE
SetBytesProcessed(int64_t bytes)556*4d6fc14bSjoerg void SetBytesProcessed(int64_t bytes) {
557*4d6fc14bSjoerg counters["bytes_per_second"] =
558*4d6fc14bSjoerg Counter(static_cast<double>(bytes), Counter::kIsRate, Counter::kIs1024);
559*4d6fc14bSjoerg }
560*4d6fc14bSjoerg
561*4d6fc14bSjoerg BENCHMARK_ALWAYS_INLINE
bytes_processed()562*4d6fc14bSjoerg int64_t bytes_processed() const {
563*4d6fc14bSjoerg if (counters.find("bytes_per_second") != counters.end())
564*4d6fc14bSjoerg return static_cast<int64_t>(counters.at("bytes_per_second"));
565*4d6fc14bSjoerg return 0;
566*4d6fc14bSjoerg }
567*4d6fc14bSjoerg
568*4d6fc14bSjoerg // If this routine is called with complexity_n > 0 and complexity report is
569*4d6fc14bSjoerg // requested for the
570*4d6fc14bSjoerg // family benchmark, then current benchmark will be part of the computation
571*4d6fc14bSjoerg // and complexity_n will
572*4d6fc14bSjoerg // represent the length of N.
573*4d6fc14bSjoerg BENCHMARK_ALWAYS_INLINE
SetComplexityN(int64_t complexity_n)574*4d6fc14bSjoerg void SetComplexityN(int64_t complexity_n) { complexity_n_ = complexity_n; }
575*4d6fc14bSjoerg
576*4d6fc14bSjoerg BENCHMARK_ALWAYS_INLINE
complexity_length_n()577*4d6fc14bSjoerg int64_t complexity_length_n() { return complexity_n_; }
578*4d6fc14bSjoerg
579*4d6fc14bSjoerg // If this routine is called with items > 0, then an items/s
580*4d6fc14bSjoerg // label is printed on the benchmark report line for the currently
581*4d6fc14bSjoerg // executing benchmark. It is typically called at the end of a processing
582*4d6fc14bSjoerg // benchmark where a processing items/second output is desired.
583*4d6fc14bSjoerg //
584*4d6fc14bSjoerg // REQUIRES: a benchmark has exited its benchmarking loop.
585*4d6fc14bSjoerg BENCHMARK_ALWAYS_INLINE
SetItemsProcessed(int64_t items)586*4d6fc14bSjoerg void SetItemsProcessed(int64_t items) {
587*4d6fc14bSjoerg counters["items_per_second"] =
588*4d6fc14bSjoerg Counter(static_cast<double>(items), benchmark::Counter::kIsRate);
589*4d6fc14bSjoerg }
590*4d6fc14bSjoerg
591*4d6fc14bSjoerg BENCHMARK_ALWAYS_INLINE
items_processed()592*4d6fc14bSjoerg int64_t items_processed() const {
593*4d6fc14bSjoerg if (counters.find("items_per_second") != counters.end())
594*4d6fc14bSjoerg return static_cast<int64_t>(counters.at("items_per_second"));
595*4d6fc14bSjoerg return 0;
596*4d6fc14bSjoerg }
597*4d6fc14bSjoerg
598*4d6fc14bSjoerg // If this routine is called, the specified label is printed at the
599*4d6fc14bSjoerg // end of the benchmark report line for the currently executing
600*4d6fc14bSjoerg // benchmark. Example:
601*4d6fc14bSjoerg // static void BM_Compress(benchmark::State& state) {
602*4d6fc14bSjoerg // ...
603*4d6fc14bSjoerg // double compress = input_size / output_size;
604*4d6fc14bSjoerg // state.SetLabel(StrFormat("compress:%.1f%%", 100.0*compression));
605*4d6fc14bSjoerg // }
606*4d6fc14bSjoerg // Produces output that looks like:
607*4d6fc14bSjoerg // BM_Compress 50 50 14115038 compress:27.3%
608*4d6fc14bSjoerg //
609*4d6fc14bSjoerg // REQUIRES: a benchmark has exited its benchmarking loop.
610*4d6fc14bSjoerg void SetLabel(const char* label);
611*4d6fc14bSjoerg
SetLabel(const std::string & str)612*4d6fc14bSjoerg void BENCHMARK_ALWAYS_INLINE SetLabel(const std::string& str) {
613*4d6fc14bSjoerg this->SetLabel(str.c_str());
614*4d6fc14bSjoerg }
615*4d6fc14bSjoerg
616*4d6fc14bSjoerg // Range arguments for this run. CHECKs if the argument has been set.
617*4d6fc14bSjoerg BENCHMARK_ALWAYS_INLINE
618*4d6fc14bSjoerg int64_t range(std::size_t pos = 0) const {
619*4d6fc14bSjoerg assert(range_.size() > pos);
620*4d6fc14bSjoerg return range_[pos];
621*4d6fc14bSjoerg }
622*4d6fc14bSjoerg
623*4d6fc14bSjoerg BENCHMARK_DEPRECATED_MSG("use 'range(0)' instead")
range_x()624*4d6fc14bSjoerg int64_t range_x() const { return range(0); }
625*4d6fc14bSjoerg
626*4d6fc14bSjoerg BENCHMARK_DEPRECATED_MSG("use 'range(1)' instead")
range_y()627*4d6fc14bSjoerg int64_t range_y() const { return range(1); }
628*4d6fc14bSjoerg
629*4d6fc14bSjoerg BENCHMARK_ALWAYS_INLINE
iterations()630*4d6fc14bSjoerg size_t iterations() const {
631*4d6fc14bSjoerg if (BENCHMARK_BUILTIN_EXPECT(!started_, false)) {
632*4d6fc14bSjoerg return 0;
633*4d6fc14bSjoerg }
634*4d6fc14bSjoerg return max_iterations - total_iterations_ + batch_leftover_;
635*4d6fc14bSjoerg }
636*4d6fc14bSjoerg
637*4d6fc14bSjoerg private
638*4d6fc14bSjoerg : // items we expect on the first cache line (ie 64 bytes of the struct)
639*4d6fc14bSjoerg // When total_iterations_ is 0, KeepRunning() and friends will return false.
640*4d6fc14bSjoerg // May be larger than max_iterations.
641*4d6fc14bSjoerg size_t total_iterations_;
642*4d6fc14bSjoerg
643*4d6fc14bSjoerg // When using KeepRunningBatch(), batch_leftover_ holds the number of
644*4d6fc14bSjoerg // iterations beyond max_iters that were run. Used to track
645*4d6fc14bSjoerg // completed_iterations_ accurately.
646*4d6fc14bSjoerg size_t batch_leftover_;
647*4d6fc14bSjoerg
648*4d6fc14bSjoerg public:
649*4d6fc14bSjoerg const size_t max_iterations;
650*4d6fc14bSjoerg
651*4d6fc14bSjoerg private:
652*4d6fc14bSjoerg bool started_;
653*4d6fc14bSjoerg bool finished_;
654*4d6fc14bSjoerg bool error_occurred_;
655*4d6fc14bSjoerg
656*4d6fc14bSjoerg private: // items we don't need on the first cache line
657*4d6fc14bSjoerg std::vector<int64_t> range_;
658*4d6fc14bSjoerg
659*4d6fc14bSjoerg int64_t complexity_n_;
660*4d6fc14bSjoerg
661*4d6fc14bSjoerg public:
662*4d6fc14bSjoerg // Container for user-defined counters.
663*4d6fc14bSjoerg UserCounters counters;
664*4d6fc14bSjoerg // Index of the executing thread. Values from [0, threads).
665*4d6fc14bSjoerg const int thread_index;
666*4d6fc14bSjoerg // Number of threads concurrently executing the benchmark.
667*4d6fc14bSjoerg const int threads;
668*4d6fc14bSjoerg
669*4d6fc14bSjoerg private:
670*4d6fc14bSjoerg State(size_t max_iters, const std::vector<int64_t>& ranges, int thread_i,
671*4d6fc14bSjoerg int n_threads, internal::ThreadTimer* timer,
672*4d6fc14bSjoerg internal::ThreadManager* manager);
673*4d6fc14bSjoerg
674*4d6fc14bSjoerg void StartKeepRunning();
675*4d6fc14bSjoerg // Implementation of KeepRunning() and KeepRunningBatch().
676*4d6fc14bSjoerg // is_batch must be true unless n is 1.
677*4d6fc14bSjoerg bool KeepRunningInternal(size_t n, bool is_batch);
678*4d6fc14bSjoerg void FinishKeepRunning();
679*4d6fc14bSjoerg internal::ThreadTimer* timer_;
680*4d6fc14bSjoerg internal::ThreadManager* manager_;
681*4d6fc14bSjoerg
682*4d6fc14bSjoerg friend struct internal::BenchmarkInstance;
683*4d6fc14bSjoerg };
684*4d6fc14bSjoerg
KeepRunning()685*4d6fc14bSjoerg inline BENCHMARK_ALWAYS_INLINE bool State::KeepRunning() {
686*4d6fc14bSjoerg return KeepRunningInternal(1, /*is_batch=*/false);
687*4d6fc14bSjoerg }
688*4d6fc14bSjoerg
KeepRunningBatch(size_t n)689*4d6fc14bSjoerg inline BENCHMARK_ALWAYS_INLINE bool State::KeepRunningBatch(size_t n) {
690*4d6fc14bSjoerg return KeepRunningInternal(n, /*is_batch=*/true);
691*4d6fc14bSjoerg }
692*4d6fc14bSjoerg
KeepRunningInternal(size_t n,bool is_batch)693*4d6fc14bSjoerg inline BENCHMARK_ALWAYS_INLINE bool State::KeepRunningInternal(size_t n,
694*4d6fc14bSjoerg bool is_batch) {
695*4d6fc14bSjoerg // total_iterations_ is set to 0 by the constructor, and always set to a
696*4d6fc14bSjoerg // nonzero value by StartKepRunning().
697*4d6fc14bSjoerg assert(n > 0);
698*4d6fc14bSjoerg // n must be 1 unless is_batch is true.
699*4d6fc14bSjoerg assert(is_batch || n == 1);
700*4d6fc14bSjoerg if (BENCHMARK_BUILTIN_EXPECT(total_iterations_ >= n, true)) {
701*4d6fc14bSjoerg total_iterations_ -= n;
702*4d6fc14bSjoerg return true;
703*4d6fc14bSjoerg }
704*4d6fc14bSjoerg if (!started_) {
705*4d6fc14bSjoerg StartKeepRunning();
706*4d6fc14bSjoerg if (!error_occurred_ && total_iterations_ >= n) {
707*4d6fc14bSjoerg total_iterations_ -= n;
708*4d6fc14bSjoerg return true;
709*4d6fc14bSjoerg }
710*4d6fc14bSjoerg }
711*4d6fc14bSjoerg // For non-batch runs, total_iterations_ must be 0 by now.
712*4d6fc14bSjoerg if (is_batch && total_iterations_ != 0) {
713*4d6fc14bSjoerg batch_leftover_ = n - total_iterations_;
714*4d6fc14bSjoerg total_iterations_ = 0;
715*4d6fc14bSjoerg return true;
716*4d6fc14bSjoerg }
717*4d6fc14bSjoerg FinishKeepRunning();
718*4d6fc14bSjoerg return false;
719*4d6fc14bSjoerg }
720*4d6fc14bSjoerg
721*4d6fc14bSjoerg struct State::StateIterator {
722*4d6fc14bSjoerg struct BENCHMARK_UNUSED Value {};
723*4d6fc14bSjoerg typedef std::forward_iterator_tag iterator_category;
724*4d6fc14bSjoerg typedef Value value_type;
725*4d6fc14bSjoerg typedef Value reference;
726*4d6fc14bSjoerg typedef Value pointer;
727*4d6fc14bSjoerg typedef std::ptrdiff_t difference_type;
728*4d6fc14bSjoerg
729*4d6fc14bSjoerg private:
730*4d6fc14bSjoerg friend class State;
731*4d6fc14bSjoerg BENCHMARK_ALWAYS_INLINE
StateIteratorStateIterator732*4d6fc14bSjoerg StateIterator() : cached_(0), parent_() {}
733*4d6fc14bSjoerg
734*4d6fc14bSjoerg BENCHMARK_ALWAYS_INLINE
StateIteratorStateIterator735*4d6fc14bSjoerg explicit StateIterator(State* st)
736*4d6fc14bSjoerg : cached_(st->error_occurred_ ? 0 : st->max_iterations), parent_(st) {}
737*4d6fc14bSjoerg
738*4d6fc14bSjoerg public:
739*4d6fc14bSjoerg BENCHMARK_ALWAYS_INLINE
740*4d6fc14bSjoerg Value operator*() const { return Value(); }
741*4d6fc14bSjoerg
742*4d6fc14bSjoerg BENCHMARK_ALWAYS_INLINE
743*4d6fc14bSjoerg StateIterator& operator++() {
744*4d6fc14bSjoerg assert(cached_ > 0);
745*4d6fc14bSjoerg --cached_;
746*4d6fc14bSjoerg return *this;
747*4d6fc14bSjoerg }
748*4d6fc14bSjoerg
749*4d6fc14bSjoerg BENCHMARK_ALWAYS_INLINE
750*4d6fc14bSjoerg bool operator!=(StateIterator const&) const {
751*4d6fc14bSjoerg if (BENCHMARK_BUILTIN_EXPECT(cached_ != 0, true)) return true;
752*4d6fc14bSjoerg parent_->FinishKeepRunning();
753*4d6fc14bSjoerg return false;
754*4d6fc14bSjoerg }
755*4d6fc14bSjoerg
756*4d6fc14bSjoerg private:
757*4d6fc14bSjoerg size_t cached_;
758*4d6fc14bSjoerg State* const parent_;
759*4d6fc14bSjoerg };
760*4d6fc14bSjoerg
begin()761*4d6fc14bSjoerg inline BENCHMARK_ALWAYS_INLINE State::StateIterator State::begin() {
762*4d6fc14bSjoerg return StateIterator(this);
763*4d6fc14bSjoerg }
end()764*4d6fc14bSjoerg inline BENCHMARK_ALWAYS_INLINE State::StateIterator State::end() {
765*4d6fc14bSjoerg StartKeepRunning();
766*4d6fc14bSjoerg return StateIterator();
767*4d6fc14bSjoerg }
768*4d6fc14bSjoerg
769*4d6fc14bSjoerg namespace internal {
770*4d6fc14bSjoerg
771*4d6fc14bSjoerg typedef void(Function)(State&);
772*4d6fc14bSjoerg
773*4d6fc14bSjoerg // ------------------------------------------------------
774*4d6fc14bSjoerg // Benchmark registration object. The BENCHMARK() macro expands
775*4d6fc14bSjoerg // into an internal::Benchmark* object. Various methods can
776*4d6fc14bSjoerg // be called on this object to change the properties of the benchmark.
777*4d6fc14bSjoerg // Each method returns "this" so that multiple method calls can
778*4d6fc14bSjoerg // chained into one expression.
779*4d6fc14bSjoerg class Benchmark {
780*4d6fc14bSjoerg public:
781*4d6fc14bSjoerg virtual ~Benchmark();
782*4d6fc14bSjoerg
783*4d6fc14bSjoerg // Note: the following methods all return "this" so that multiple
784*4d6fc14bSjoerg // method calls can be chained together in one expression.
785*4d6fc14bSjoerg
786*4d6fc14bSjoerg // Run this benchmark once with "x" as the extra argument passed
787*4d6fc14bSjoerg // to the function.
788*4d6fc14bSjoerg // REQUIRES: The function passed to the constructor must accept an arg1.
789*4d6fc14bSjoerg Benchmark* Arg(int64_t x);
790*4d6fc14bSjoerg
791*4d6fc14bSjoerg // Run this benchmark with the given time unit for the generated output report
792*4d6fc14bSjoerg Benchmark* Unit(TimeUnit unit);
793*4d6fc14bSjoerg
794*4d6fc14bSjoerg // Run this benchmark once for a number of values picked from the
795*4d6fc14bSjoerg // range [start..limit]. (start and limit are always picked.)
796*4d6fc14bSjoerg // REQUIRES: The function passed to the constructor must accept an arg1.
797*4d6fc14bSjoerg Benchmark* Range(int64_t start, int64_t limit);
798*4d6fc14bSjoerg
799*4d6fc14bSjoerg // Run this benchmark once for all values in the range [start..limit] with
800*4d6fc14bSjoerg // specific step
801*4d6fc14bSjoerg // REQUIRES: The function passed to the constructor must accept an arg1.
802*4d6fc14bSjoerg Benchmark* DenseRange(int64_t start, int64_t limit, int step = 1);
803*4d6fc14bSjoerg
804*4d6fc14bSjoerg // Run this benchmark once with "args" as the extra arguments passed
805*4d6fc14bSjoerg // to the function.
806*4d6fc14bSjoerg // REQUIRES: The function passed to the constructor must accept arg1, arg2 ...
807*4d6fc14bSjoerg Benchmark* Args(const std::vector<int64_t>& args);
808*4d6fc14bSjoerg
809*4d6fc14bSjoerg // Equivalent to Args({x, y})
810*4d6fc14bSjoerg // NOTE: This is a legacy C++03 interface provided for compatibility only.
811*4d6fc14bSjoerg // New code should use 'Args'.
ArgPair(int64_t x,int64_t y)812*4d6fc14bSjoerg Benchmark* ArgPair(int64_t x, int64_t y) {
813*4d6fc14bSjoerg std::vector<int64_t> args;
814*4d6fc14bSjoerg args.push_back(x);
815*4d6fc14bSjoerg args.push_back(y);
816*4d6fc14bSjoerg return Args(args);
817*4d6fc14bSjoerg }
818*4d6fc14bSjoerg
819*4d6fc14bSjoerg // Run this benchmark once for a number of values picked from the
820*4d6fc14bSjoerg // ranges [start..limit]. (starts and limits are always picked.)
821*4d6fc14bSjoerg // REQUIRES: The function passed to the constructor must accept arg1, arg2 ...
822*4d6fc14bSjoerg Benchmark* Ranges(const std::vector<std::pair<int64_t, int64_t> >& ranges);
823*4d6fc14bSjoerg
824*4d6fc14bSjoerg // Equivalent to ArgNames({name})
825*4d6fc14bSjoerg Benchmark* ArgName(const std::string& name);
826*4d6fc14bSjoerg
827*4d6fc14bSjoerg // Set the argument names to display in the benchmark name. If not called,
828*4d6fc14bSjoerg // only argument values will be shown.
829*4d6fc14bSjoerg Benchmark* ArgNames(const std::vector<std::string>& names);
830*4d6fc14bSjoerg
831*4d6fc14bSjoerg // Equivalent to Ranges({{lo1, hi1}, {lo2, hi2}}).
832*4d6fc14bSjoerg // NOTE: This is a legacy C++03 interface provided for compatibility only.
833*4d6fc14bSjoerg // New code should use 'Ranges'.
RangePair(int64_t lo1,int64_t hi1,int64_t lo2,int64_t hi2)834*4d6fc14bSjoerg Benchmark* RangePair(int64_t lo1, int64_t hi1, int64_t lo2, int64_t hi2) {
835*4d6fc14bSjoerg std::vector<std::pair<int64_t, int64_t> > ranges;
836*4d6fc14bSjoerg ranges.push_back(std::make_pair(lo1, hi1));
837*4d6fc14bSjoerg ranges.push_back(std::make_pair(lo2, hi2));
838*4d6fc14bSjoerg return Ranges(ranges);
839*4d6fc14bSjoerg }
840*4d6fc14bSjoerg
841*4d6fc14bSjoerg // Pass this benchmark object to *func, which can customize
842*4d6fc14bSjoerg // the benchmark by calling various methods like Arg, Args,
843*4d6fc14bSjoerg // Threads, etc.
844*4d6fc14bSjoerg Benchmark* Apply(void (*func)(Benchmark* benchmark));
845*4d6fc14bSjoerg
846*4d6fc14bSjoerg // Set the range multiplier for non-dense range. If not called, the range
847*4d6fc14bSjoerg // multiplier kRangeMultiplier will be used.
848*4d6fc14bSjoerg Benchmark* RangeMultiplier(int multiplier);
849*4d6fc14bSjoerg
850*4d6fc14bSjoerg // Set the minimum amount of time to use when running this benchmark. This
851*4d6fc14bSjoerg // option overrides the `benchmark_min_time` flag.
852*4d6fc14bSjoerg // REQUIRES: `t > 0` and `Iterations` has not been called on this benchmark.
853*4d6fc14bSjoerg Benchmark* MinTime(double t);
854*4d6fc14bSjoerg
855*4d6fc14bSjoerg // Specify the amount of iterations that should be run by this benchmark.
856*4d6fc14bSjoerg // REQUIRES: 'n > 0' and `MinTime` has not been called on this benchmark.
857*4d6fc14bSjoerg //
858*4d6fc14bSjoerg // NOTE: This function should only be used when *exact* iteration control is
859*4d6fc14bSjoerg // needed and never to control or limit how long a benchmark runs, where
860*4d6fc14bSjoerg // `--benchmark_min_time=N` or `MinTime(...)` should be used instead.
861*4d6fc14bSjoerg Benchmark* Iterations(size_t n);
862*4d6fc14bSjoerg
863*4d6fc14bSjoerg // Specify the amount of times to repeat this benchmark. This option overrides
864*4d6fc14bSjoerg // the `benchmark_repetitions` flag.
865*4d6fc14bSjoerg // REQUIRES: `n > 0`
866*4d6fc14bSjoerg Benchmark* Repetitions(int n);
867*4d6fc14bSjoerg
868*4d6fc14bSjoerg // Specify if each repetition of the benchmark should be reported separately
869*4d6fc14bSjoerg // or if only the final statistics should be reported. If the benchmark
870*4d6fc14bSjoerg // is not repeated then the single result is always reported.
871*4d6fc14bSjoerg // Applies to *ALL* reporters (display and file).
872*4d6fc14bSjoerg Benchmark* ReportAggregatesOnly(bool value = true);
873*4d6fc14bSjoerg
874*4d6fc14bSjoerg // Same as ReportAggregatesOnly(), but applies to display reporter only.
875*4d6fc14bSjoerg Benchmark* DisplayAggregatesOnly(bool value = true);
876*4d6fc14bSjoerg
877*4d6fc14bSjoerg // If a particular benchmark is I/O bound, runs multiple threads internally or
878*4d6fc14bSjoerg // if for some reason CPU timings are not representative, call this method. If
879*4d6fc14bSjoerg // called, the elapsed time will be used to control how many iterations are
880*4d6fc14bSjoerg // run, and in the printing of items/second or MB/seconds values. If not
881*4d6fc14bSjoerg // called, the cpu time used by the benchmark will be used.
882*4d6fc14bSjoerg Benchmark* UseRealTime();
883*4d6fc14bSjoerg
884*4d6fc14bSjoerg // If a benchmark must measure time manually (e.g. if GPU execution time is
885*4d6fc14bSjoerg // being
886*4d6fc14bSjoerg // measured), call this method. If called, each benchmark iteration should
887*4d6fc14bSjoerg // call
888*4d6fc14bSjoerg // SetIterationTime(seconds) to report the measured time, which will be used
889*4d6fc14bSjoerg // to control how many iterations are run, and in the printing of items/second
890*4d6fc14bSjoerg // or MB/second values.
891*4d6fc14bSjoerg Benchmark* UseManualTime();
892*4d6fc14bSjoerg
893*4d6fc14bSjoerg // Set the asymptotic computational complexity for the benchmark. If called
894*4d6fc14bSjoerg // the asymptotic computational complexity will be shown on the output.
895*4d6fc14bSjoerg Benchmark* Complexity(BigO complexity = benchmark::oAuto);
896*4d6fc14bSjoerg
897*4d6fc14bSjoerg // Set the asymptotic computational complexity for the benchmark. If called
898*4d6fc14bSjoerg // the asymptotic computational complexity will be shown on the output.
899*4d6fc14bSjoerg Benchmark* Complexity(BigOFunc* complexity);
900*4d6fc14bSjoerg
901*4d6fc14bSjoerg // Add this statistics to be computed over all the values of benchmark run
902*4d6fc14bSjoerg Benchmark* ComputeStatistics(std::string name, StatisticsFunc* statistics);
903*4d6fc14bSjoerg
904*4d6fc14bSjoerg // Support for running multiple copies of the same benchmark concurrently
905*4d6fc14bSjoerg // in multiple threads. This may be useful when measuring the scaling
906*4d6fc14bSjoerg // of some piece of code.
907*4d6fc14bSjoerg
908*4d6fc14bSjoerg // Run one instance of this benchmark concurrently in t threads.
909*4d6fc14bSjoerg Benchmark* Threads(int t);
910*4d6fc14bSjoerg
911*4d6fc14bSjoerg // Pick a set of values T from [min_threads,max_threads].
912*4d6fc14bSjoerg // min_threads and max_threads are always included in T. Run this
913*4d6fc14bSjoerg // benchmark once for each value in T. The benchmark run for a
914*4d6fc14bSjoerg // particular value t consists of t threads running the benchmark
915*4d6fc14bSjoerg // function concurrently. For example, consider:
916*4d6fc14bSjoerg // BENCHMARK(Foo)->ThreadRange(1,16);
917*4d6fc14bSjoerg // This will run the following benchmarks:
918*4d6fc14bSjoerg // Foo in 1 thread
919*4d6fc14bSjoerg // Foo in 2 threads
920*4d6fc14bSjoerg // Foo in 4 threads
921*4d6fc14bSjoerg // Foo in 8 threads
922*4d6fc14bSjoerg // Foo in 16 threads
923*4d6fc14bSjoerg Benchmark* ThreadRange(int min_threads, int max_threads);
924*4d6fc14bSjoerg
925*4d6fc14bSjoerg // For each value n in the range, run this benchmark once using n threads.
926*4d6fc14bSjoerg // min_threads and max_threads are always included in the range.
927*4d6fc14bSjoerg // stride specifies the increment. E.g. DenseThreadRange(1, 8, 3) starts
928*4d6fc14bSjoerg // a benchmark with 1, 4, 7 and 8 threads.
929*4d6fc14bSjoerg Benchmark* DenseThreadRange(int min_threads, int max_threads, int stride = 1);
930*4d6fc14bSjoerg
931*4d6fc14bSjoerg // Equivalent to ThreadRange(NumCPUs(), NumCPUs())
932*4d6fc14bSjoerg Benchmark* ThreadPerCpu();
933*4d6fc14bSjoerg
934*4d6fc14bSjoerg virtual void Run(State& state) = 0;
935*4d6fc14bSjoerg
936*4d6fc14bSjoerg protected:
937*4d6fc14bSjoerg explicit Benchmark(const char* name);
938*4d6fc14bSjoerg Benchmark(Benchmark const&);
939*4d6fc14bSjoerg void SetName(const char* name);
940*4d6fc14bSjoerg
941*4d6fc14bSjoerg int ArgsCnt() const;
942*4d6fc14bSjoerg
943*4d6fc14bSjoerg private:
944*4d6fc14bSjoerg friend class BenchmarkFamilies;
945*4d6fc14bSjoerg
946*4d6fc14bSjoerg std::string name_;
947*4d6fc14bSjoerg AggregationReportMode aggregation_report_mode_;
948*4d6fc14bSjoerg std::vector<std::string> arg_names_; // Args for all benchmark runs
949*4d6fc14bSjoerg std::vector<std::vector<int64_t> > args_; // Args for all benchmark runs
950*4d6fc14bSjoerg TimeUnit time_unit_;
951*4d6fc14bSjoerg int range_multiplier_;
952*4d6fc14bSjoerg double min_time_;
953*4d6fc14bSjoerg size_t iterations_;
954*4d6fc14bSjoerg int repetitions_;
955*4d6fc14bSjoerg bool use_real_time_;
956*4d6fc14bSjoerg bool use_manual_time_;
957*4d6fc14bSjoerg BigO complexity_;
958*4d6fc14bSjoerg BigOFunc* complexity_lambda_;
959*4d6fc14bSjoerg std::vector<Statistics> statistics_;
960*4d6fc14bSjoerg std::vector<int> thread_counts_;
961*4d6fc14bSjoerg
962*4d6fc14bSjoerg Benchmark& operator=(Benchmark const&);
963*4d6fc14bSjoerg };
964*4d6fc14bSjoerg
965*4d6fc14bSjoerg } // namespace internal
966*4d6fc14bSjoerg
967*4d6fc14bSjoerg // Create and register a benchmark with the specified 'name' that invokes
968*4d6fc14bSjoerg // the specified functor 'fn'.
969*4d6fc14bSjoerg //
970*4d6fc14bSjoerg // RETURNS: A pointer to the registered benchmark.
971*4d6fc14bSjoerg internal::Benchmark* RegisterBenchmark(const char* name,
972*4d6fc14bSjoerg internal::Function* fn);
973*4d6fc14bSjoerg
974*4d6fc14bSjoerg #if defined(BENCHMARK_HAS_CXX11)
975*4d6fc14bSjoerg template <class Lambda>
976*4d6fc14bSjoerg internal::Benchmark* RegisterBenchmark(const char* name, Lambda&& fn);
977*4d6fc14bSjoerg #endif
978*4d6fc14bSjoerg
979*4d6fc14bSjoerg // Remove all registered benchmarks. All pointers to previously registered
980*4d6fc14bSjoerg // benchmarks are invalidated.
981*4d6fc14bSjoerg void ClearRegisteredBenchmarks();
982*4d6fc14bSjoerg
983*4d6fc14bSjoerg namespace internal {
984*4d6fc14bSjoerg // The class used to hold all Benchmarks created from static function.
985*4d6fc14bSjoerg // (ie those created using the BENCHMARK(...) macros.
986*4d6fc14bSjoerg class FunctionBenchmark : public Benchmark {
987*4d6fc14bSjoerg public:
FunctionBenchmark(const char * name,Function * func)988*4d6fc14bSjoerg FunctionBenchmark(const char* name, Function* func)
989*4d6fc14bSjoerg : Benchmark(name), func_(func) {}
990*4d6fc14bSjoerg
991*4d6fc14bSjoerg virtual void Run(State& st);
992*4d6fc14bSjoerg
993*4d6fc14bSjoerg private:
994*4d6fc14bSjoerg Function* func_;
995*4d6fc14bSjoerg };
996*4d6fc14bSjoerg
997*4d6fc14bSjoerg #ifdef BENCHMARK_HAS_CXX11
998*4d6fc14bSjoerg template <class Lambda>
999*4d6fc14bSjoerg class LambdaBenchmark : public Benchmark {
1000*4d6fc14bSjoerg public:
Run(State & st)1001*4d6fc14bSjoerg virtual void Run(State& st) { lambda_(st); }
1002*4d6fc14bSjoerg
1003*4d6fc14bSjoerg private:
1004*4d6fc14bSjoerg template <class OLambda>
LambdaBenchmark(const char * name,OLambda && lam)1005*4d6fc14bSjoerg LambdaBenchmark(const char* name, OLambda&& lam)
1006*4d6fc14bSjoerg : Benchmark(name), lambda_(std::forward<OLambda>(lam)) {}
1007*4d6fc14bSjoerg
1008*4d6fc14bSjoerg LambdaBenchmark(LambdaBenchmark const&) = delete;
1009*4d6fc14bSjoerg
1010*4d6fc14bSjoerg private:
1011*4d6fc14bSjoerg template <class Lam>
1012*4d6fc14bSjoerg friend Benchmark* ::benchmark::RegisterBenchmark(const char*, Lam&&);
1013*4d6fc14bSjoerg
1014*4d6fc14bSjoerg Lambda lambda_;
1015*4d6fc14bSjoerg };
1016*4d6fc14bSjoerg #endif
1017*4d6fc14bSjoerg
1018*4d6fc14bSjoerg } // namespace internal
1019*4d6fc14bSjoerg
RegisterBenchmark(const char * name,internal::Function * fn)1020*4d6fc14bSjoerg inline internal::Benchmark* RegisterBenchmark(const char* name,
1021*4d6fc14bSjoerg internal::Function* fn) {
1022*4d6fc14bSjoerg return internal::RegisterBenchmarkInternal(
1023*4d6fc14bSjoerg ::new internal::FunctionBenchmark(name, fn));
1024*4d6fc14bSjoerg }
1025*4d6fc14bSjoerg
1026*4d6fc14bSjoerg #ifdef BENCHMARK_HAS_CXX11
1027*4d6fc14bSjoerg template <class Lambda>
RegisterBenchmark(const char * name,Lambda && fn)1028*4d6fc14bSjoerg internal::Benchmark* RegisterBenchmark(const char* name, Lambda&& fn) {
1029*4d6fc14bSjoerg using BenchType =
1030*4d6fc14bSjoerg internal::LambdaBenchmark<typename std::decay<Lambda>::type>;
1031*4d6fc14bSjoerg return internal::RegisterBenchmarkInternal(
1032*4d6fc14bSjoerg ::new BenchType(name, std::forward<Lambda>(fn)));
1033*4d6fc14bSjoerg }
1034*4d6fc14bSjoerg #endif
1035*4d6fc14bSjoerg
1036*4d6fc14bSjoerg #if defined(BENCHMARK_HAS_CXX11) && \
1037*4d6fc14bSjoerg (!defined(BENCHMARK_GCC_VERSION) || BENCHMARK_GCC_VERSION >= 409)
1038*4d6fc14bSjoerg template <class Lambda, class... Args>
RegisterBenchmark(const char * name,Lambda && fn,Args &&...args)1039*4d6fc14bSjoerg internal::Benchmark* RegisterBenchmark(const char* name, Lambda&& fn,
1040*4d6fc14bSjoerg Args&&... args) {
1041*4d6fc14bSjoerg return benchmark::RegisterBenchmark(
1042*4d6fc14bSjoerg name, [=](benchmark::State& st) { fn(st, args...); });
1043*4d6fc14bSjoerg }
1044*4d6fc14bSjoerg #else
1045*4d6fc14bSjoerg #define BENCHMARK_HAS_NO_VARIADIC_REGISTER_BENCHMARK
1046*4d6fc14bSjoerg #endif
1047*4d6fc14bSjoerg
1048*4d6fc14bSjoerg // The base class for all fixture tests.
1049*4d6fc14bSjoerg class Fixture : public internal::Benchmark {
1050*4d6fc14bSjoerg public:
Fixture()1051*4d6fc14bSjoerg Fixture() : internal::Benchmark("") {}
1052*4d6fc14bSjoerg
Run(State & st)1053*4d6fc14bSjoerg virtual void Run(State& st) {
1054*4d6fc14bSjoerg this->SetUp(st);
1055*4d6fc14bSjoerg this->BenchmarkCase(st);
1056*4d6fc14bSjoerg this->TearDown(st);
1057*4d6fc14bSjoerg }
1058*4d6fc14bSjoerg
1059*4d6fc14bSjoerg // These will be deprecated ...
SetUp(const State &)1060*4d6fc14bSjoerg virtual void SetUp(const State&) {}
TearDown(const State &)1061*4d6fc14bSjoerg virtual void TearDown(const State&) {}
1062*4d6fc14bSjoerg // ... In favor of these.
SetUp(State & st)1063*4d6fc14bSjoerg virtual void SetUp(State& st) { SetUp(const_cast<const State&>(st)); }
TearDown(State & st)1064*4d6fc14bSjoerg virtual void TearDown(State& st) { TearDown(const_cast<const State&>(st)); }
1065*4d6fc14bSjoerg
1066*4d6fc14bSjoerg protected:
1067*4d6fc14bSjoerg virtual void BenchmarkCase(State&) = 0;
1068*4d6fc14bSjoerg };
1069*4d6fc14bSjoerg
1070*4d6fc14bSjoerg } // namespace benchmark
1071*4d6fc14bSjoerg
1072*4d6fc14bSjoerg // ------------------------------------------------------
1073*4d6fc14bSjoerg // Macro to register benchmarks
1074*4d6fc14bSjoerg
1075*4d6fc14bSjoerg // Check that __COUNTER__ is defined and that __COUNTER__ increases by 1
1076*4d6fc14bSjoerg // every time it is expanded. X + 1 == X + 0 is used in case X is defined to be
1077*4d6fc14bSjoerg // empty. If X is empty the expression becomes (+1 == +0).
1078*4d6fc14bSjoerg #if defined(__COUNTER__) && (__COUNTER__ + 1 == __COUNTER__ + 0)
1079*4d6fc14bSjoerg #define BENCHMARK_PRIVATE_UNIQUE_ID __COUNTER__
1080*4d6fc14bSjoerg #else
1081*4d6fc14bSjoerg #define BENCHMARK_PRIVATE_UNIQUE_ID __LINE__
1082*4d6fc14bSjoerg #endif
1083*4d6fc14bSjoerg
1084*4d6fc14bSjoerg // Helpers for generating unique variable names
1085*4d6fc14bSjoerg #define BENCHMARK_PRIVATE_NAME(n) \
1086*4d6fc14bSjoerg BENCHMARK_PRIVATE_CONCAT(_benchmark_, BENCHMARK_PRIVATE_UNIQUE_ID, n)
1087*4d6fc14bSjoerg #define BENCHMARK_PRIVATE_CONCAT(a, b, c) BENCHMARK_PRIVATE_CONCAT2(a, b, c)
1088*4d6fc14bSjoerg #define BENCHMARK_PRIVATE_CONCAT2(a, b, c) a##b##c
1089*4d6fc14bSjoerg
1090*4d6fc14bSjoerg #define BENCHMARK_PRIVATE_DECLARE(n) \
1091*4d6fc14bSjoerg static ::benchmark::internal::Benchmark* BENCHMARK_PRIVATE_NAME(n) \
1092*4d6fc14bSjoerg BENCHMARK_UNUSED
1093*4d6fc14bSjoerg
1094*4d6fc14bSjoerg #define BENCHMARK(n) \
1095*4d6fc14bSjoerg BENCHMARK_PRIVATE_DECLARE(n) = \
1096*4d6fc14bSjoerg (::benchmark::internal::RegisterBenchmarkInternal( \
1097*4d6fc14bSjoerg new ::benchmark::internal::FunctionBenchmark(#n, n)))
1098*4d6fc14bSjoerg
1099*4d6fc14bSjoerg // Old-style macros
1100*4d6fc14bSjoerg #define BENCHMARK_WITH_ARG(n, a) BENCHMARK(n)->Arg((a))
1101*4d6fc14bSjoerg #define BENCHMARK_WITH_ARG2(n, a1, a2) BENCHMARK(n)->Args({(a1), (a2)})
1102*4d6fc14bSjoerg #define BENCHMARK_WITH_UNIT(n, t) BENCHMARK(n)->Unit((t))
1103*4d6fc14bSjoerg #define BENCHMARK_RANGE(n, lo, hi) BENCHMARK(n)->Range((lo), (hi))
1104*4d6fc14bSjoerg #define BENCHMARK_RANGE2(n, l1, h1, l2, h2) \
1105*4d6fc14bSjoerg BENCHMARK(n)->RangePair({{(l1), (h1)}, {(l2), (h2)}})
1106*4d6fc14bSjoerg
1107*4d6fc14bSjoerg #ifdef BENCHMARK_HAS_CXX11
1108*4d6fc14bSjoerg
1109*4d6fc14bSjoerg // Register a benchmark which invokes the function specified by `func`
1110*4d6fc14bSjoerg // with the additional arguments specified by `...`.
1111*4d6fc14bSjoerg //
1112*4d6fc14bSjoerg // For example:
1113*4d6fc14bSjoerg //
1114*4d6fc14bSjoerg // template <class ...ExtraArgs>`
1115*4d6fc14bSjoerg // void BM_takes_args(benchmark::State& state, ExtraArgs&&... extra_args) {
1116*4d6fc14bSjoerg // [...]
1117*4d6fc14bSjoerg //}
1118*4d6fc14bSjoerg // /* Registers a benchmark named "BM_takes_args/int_string_test` */
1119*4d6fc14bSjoerg // BENCHMARK_CAPTURE(BM_takes_args, int_string_test, 42, std::string("abc"));
1120*4d6fc14bSjoerg #define BENCHMARK_CAPTURE(func, test_case_name, ...) \
1121*4d6fc14bSjoerg BENCHMARK_PRIVATE_DECLARE(func) = \
1122*4d6fc14bSjoerg (::benchmark::internal::RegisterBenchmarkInternal( \
1123*4d6fc14bSjoerg new ::benchmark::internal::FunctionBenchmark( \
1124*4d6fc14bSjoerg #func "/" #test_case_name, \
1125*4d6fc14bSjoerg [](::benchmark::State& st) { func(st, __VA_ARGS__); })))
1126*4d6fc14bSjoerg
1127*4d6fc14bSjoerg #endif // BENCHMARK_HAS_CXX11
1128*4d6fc14bSjoerg
1129*4d6fc14bSjoerg // This will register a benchmark for a templatized function. For example:
1130*4d6fc14bSjoerg //
1131*4d6fc14bSjoerg // template<int arg>
1132*4d6fc14bSjoerg // void BM_Foo(int iters);
1133*4d6fc14bSjoerg //
1134*4d6fc14bSjoerg // BENCHMARK_TEMPLATE(BM_Foo, 1);
1135*4d6fc14bSjoerg //
1136*4d6fc14bSjoerg // will register BM_Foo<1> as a benchmark.
1137*4d6fc14bSjoerg #define BENCHMARK_TEMPLATE1(n, a) \
1138*4d6fc14bSjoerg BENCHMARK_PRIVATE_DECLARE(n) = \
1139*4d6fc14bSjoerg (::benchmark::internal::RegisterBenchmarkInternal( \
1140*4d6fc14bSjoerg new ::benchmark::internal::FunctionBenchmark(#n "<" #a ">", n<a>)))
1141*4d6fc14bSjoerg
1142*4d6fc14bSjoerg #define BENCHMARK_TEMPLATE2(n, a, b) \
1143*4d6fc14bSjoerg BENCHMARK_PRIVATE_DECLARE(n) = \
1144*4d6fc14bSjoerg (::benchmark::internal::RegisterBenchmarkInternal( \
1145*4d6fc14bSjoerg new ::benchmark::internal::FunctionBenchmark(#n "<" #a "," #b ">", \
1146*4d6fc14bSjoerg n<a, b>)))
1147*4d6fc14bSjoerg
1148*4d6fc14bSjoerg #ifdef BENCHMARK_HAS_CXX11
1149*4d6fc14bSjoerg #define BENCHMARK_TEMPLATE(n, ...) \
1150*4d6fc14bSjoerg BENCHMARK_PRIVATE_DECLARE(n) = \
1151*4d6fc14bSjoerg (::benchmark::internal::RegisterBenchmarkInternal( \
1152*4d6fc14bSjoerg new ::benchmark::internal::FunctionBenchmark( \
1153*4d6fc14bSjoerg #n "<" #__VA_ARGS__ ">", n<__VA_ARGS__>)))
1154*4d6fc14bSjoerg #else
1155*4d6fc14bSjoerg #define BENCHMARK_TEMPLATE(n, a) BENCHMARK_TEMPLATE1(n, a)
1156*4d6fc14bSjoerg #endif
1157*4d6fc14bSjoerg
1158*4d6fc14bSjoerg #define BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \
1159*4d6fc14bSjoerg class BaseClass##_##Method##_Benchmark : public BaseClass { \
1160*4d6fc14bSjoerg public: \
1161*4d6fc14bSjoerg BaseClass##_##Method##_Benchmark() : BaseClass() { \
1162*4d6fc14bSjoerg this->SetName(#BaseClass "/" #Method); \
1163*4d6fc14bSjoerg } \
1164*4d6fc14bSjoerg \
1165*4d6fc14bSjoerg protected: \
1166*4d6fc14bSjoerg virtual void BenchmarkCase(::benchmark::State&); \
1167*4d6fc14bSjoerg };
1168*4d6fc14bSjoerg
1169*4d6fc14bSjoerg #define BENCHMARK_TEMPLATE1_PRIVATE_DECLARE_F(BaseClass, Method, a) \
1170*4d6fc14bSjoerg class BaseClass##_##Method##_Benchmark : public BaseClass<a> { \
1171*4d6fc14bSjoerg public: \
1172*4d6fc14bSjoerg BaseClass##_##Method##_Benchmark() : BaseClass<a>() { \
1173*4d6fc14bSjoerg this->SetName(#BaseClass "<" #a ">/" #Method); \
1174*4d6fc14bSjoerg } \
1175*4d6fc14bSjoerg \
1176*4d6fc14bSjoerg protected: \
1177*4d6fc14bSjoerg virtual void BenchmarkCase(::benchmark::State&); \
1178*4d6fc14bSjoerg };
1179*4d6fc14bSjoerg
1180*4d6fc14bSjoerg #define BENCHMARK_TEMPLATE2_PRIVATE_DECLARE_F(BaseClass, Method, a, b) \
1181*4d6fc14bSjoerg class BaseClass##_##Method##_Benchmark : public BaseClass<a, b> { \
1182*4d6fc14bSjoerg public: \
1183*4d6fc14bSjoerg BaseClass##_##Method##_Benchmark() : BaseClass<a, b>() { \
1184*4d6fc14bSjoerg this->SetName(#BaseClass "<" #a "," #b ">/" #Method); \
1185*4d6fc14bSjoerg } \
1186*4d6fc14bSjoerg \
1187*4d6fc14bSjoerg protected: \
1188*4d6fc14bSjoerg virtual void BenchmarkCase(::benchmark::State&); \
1189*4d6fc14bSjoerg };
1190*4d6fc14bSjoerg
1191*4d6fc14bSjoerg #ifdef BENCHMARK_HAS_CXX11
1192*4d6fc14bSjoerg #define BENCHMARK_TEMPLATE_PRIVATE_DECLARE_F(BaseClass, Method, ...) \
1193*4d6fc14bSjoerg class BaseClass##_##Method##_Benchmark : public BaseClass<__VA_ARGS__> { \
1194*4d6fc14bSjoerg public: \
1195*4d6fc14bSjoerg BaseClass##_##Method##_Benchmark() : BaseClass<__VA_ARGS__>() { \
1196*4d6fc14bSjoerg this->SetName(#BaseClass "<" #__VA_ARGS__ ">/" #Method); \
1197*4d6fc14bSjoerg } \
1198*4d6fc14bSjoerg \
1199*4d6fc14bSjoerg protected: \
1200*4d6fc14bSjoerg virtual void BenchmarkCase(::benchmark::State&); \
1201*4d6fc14bSjoerg };
1202*4d6fc14bSjoerg #else
1203*4d6fc14bSjoerg #define BENCHMARK_TEMPLATE_PRIVATE_DECLARE_F(n, a) \
1204*4d6fc14bSjoerg BENCHMARK_TEMPLATE1_PRIVATE_DECLARE_F(n, a)
1205*4d6fc14bSjoerg #endif
1206*4d6fc14bSjoerg
1207*4d6fc14bSjoerg #define BENCHMARK_DEFINE_F(BaseClass, Method) \
1208*4d6fc14bSjoerg BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \
1209*4d6fc14bSjoerg void BaseClass##_##Method##_Benchmark::BenchmarkCase
1210*4d6fc14bSjoerg
1211*4d6fc14bSjoerg #define BENCHMARK_TEMPLATE1_DEFINE_F(BaseClass, Method, a) \
1212*4d6fc14bSjoerg BENCHMARK_TEMPLATE1_PRIVATE_DECLARE_F(BaseClass, Method, a) \
1213*4d6fc14bSjoerg void BaseClass##_##Method##_Benchmark::BenchmarkCase
1214*4d6fc14bSjoerg
1215*4d6fc14bSjoerg #define BENCHMARK_TEMPLATE2_DEFINE_F(BaseClass, Method, a, b) \
1216*4d6fc14bSjoerg BENCHMARK_TEMPLATE2_PRIVATE_DECLARE_F(BaseClass, Method, a, b) \
1217*4d6fc14bSjoerg void BaseClass##_##Method##_Benchmark::BenchmarkCase
1218*4d6fc14bSjoerg
1219*4d6fc14bSjoerg #ifdef BENCHMARK_HAS_CXX11
1220*4d6fc14bSjoerg #define BENCHMARK_TEMPLATE_DEFINE_F(BaseClass, Method, ...) \
1221*4d6fc14bSjoerg BENCHMARK_TEMPLATE_PRIVATE_DECLARE_F(BaseClass, Method, __VA_ARGS__) \
1222*4d6fc14bSjoerg void BaseClass##_##Method##_Benchmark::BenchmarkCase
1223*4d6fc14bSjoerg #else
1224*4d6fc14bSjoerg #define BENCHMARK_TEMPLATE_DEFINE_F(BaseClass, Method, a) \
1225*4d6fc14bSjoerg BENCHMARK_TEMPLATE1_DEFINE_F(BaseClass, Method, a)
1226*4d6fc14bSjoerg #endif
1227*4d6fc14bSjoerg
1228*4d6fc14bSjoerg #define BENCHMARK_REGISTER_F(BaseClass, Method) \
1229*4d6fc14bSjoerg BENCHMARK_PRIVATE_REGISTER_F(BaseClass##_##Method##_Benchmark)
1230*4d6fc14bSjoerg
1231*4d6fc14bSjoerg #define BENCHMARK_PRIVATE_REGISTER_F(TestName) \
1232*4d6fc14bSjoerg BENCHMARK_PRIVATE_DECLARE(TestName) = \
1233*4d6fc14bSjoerg (::benchmark::internal::RegisterBenchmarkInternal(new TestName()))
1234*4d6fc14bSjoerg
1235*4d6fc14bSjoerg // This macro will define and register a benchmark within a fixture class.
1236*4d6fc14bSjoerg #define BENCHMARK_F(BaseClass, Method) \
1237*4d6fc14bSjoerg BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \
1238*4d6fc14bSjoerg BENCHMARK_REGISTER_F(BaseClass, Method); \
1239*4d6fc14bSjoerg void BaseClass##_##Method##_Benchmark::BenchmarkCase
1240*4d6fc14bSjoerg
1241*4d6fc14bSjoerg #define BENCHMARK_TEMPLATE1_F(BaseClass, Method, a) \
1242*4d6fc14bSjoerg BENCHMARK_TEMPLATE1_PRIVATE_DECLARE_F(BaseClass, Method, a) \
1243*4d6fc14bSjoerg BENCHMARK_REGISTER_F(BaseClass, Method); \
1244*4d6fc14bSjoerg void BaseClass##_##Method##_Benchmark::BenchmarkCase
1245*4d6fc14bSjoerg
1246*4d6fc14bSjoerg #define BENCHMARK_TEMPLATE2_F(BaseClass, Method, a, b) \
1247*4d6fc14bSjoerg BENCHMARK_TEMPLATE2_PRIVATE_DECLARE_F(BaseClass, Method, a, b) \
1248*4d6fc14bSjoerg BENCHMARK_REGISTER_F(BaseClass, Method); \
1249*4d6fc14bSjoerg void BaseClass##_##Method##_Benchmark::BenchmarkCase
1250*4d6fc14bSjoerg
1251*4d6fc14bSjoerg #ifdef BENCHMARK_HAS_CXX11
1252*4d6fc14bSjoerg #define BENCHMARK_TEMPLATE_F(BaseClass, Method, ...) \
1253*4d6fc14bSjoerg BENCHMARK_TEMPLATE_PRIVATE_DECLARE_F(BaseClass, Method, __VA_ARGS__) \
1254*4d6fc14bSjoerg BENCHMARK_REGISTER_F(BaseClass, Method); \
1255*4d6fc14bSjoerg void BaseClass##_##Method##_Benchmark::BenchmarkCase
1256*4d6fc14bSjoerg #else
1257*4d6fc14bSjoerg #define BENCHMARK_TEMPLATE_F(BaseClass, Method, a) \
1258*4d6fc14bSjoerg BENCHMARK_TEMPLATE1_F(BaseClass, Method, a)
1259*4d6fc14bSjoerg #endif
1260*4d6fc14bSjoerg
1261*4d6fc14bSjoerg // Helper macro to create a main routine in a test that runs the benchmarks
1262*4d6fc14bSjoerg #define BENCHMARK_MAIN() \
1263*4d6fc14bSjoerg int main(int argc, char** argv) { \
1264*4d6fc14bSjoerg ::benchmark::Initialize(&argc, argv); \
1265*4d6fc14bSjoerg if (::benchmark::ReportUnrecognizedArguments(argc, argv)) return 1; \
1266*4d6fc14bSjoerg ::benchmark::RunSpecifiedBenchmarks(); \
1267*4d6fc14bSjoerg } \
1268*4d6fc14bSjoerg int main(int, char**)
1269*4d6fc14bSjoerg
1270*4d6fc14bSjoerg // ------------------------------------------------------
1271*4d6fc14bSjoerg // Benchmark Reporters
1272*4d6fc14bSjoerg
1273*4d6fc14bSjoerg namespace benchmark {
1274*4d6fc14bSjoerg
1275*4d6fc14bSjoerg struct CPUInfo {
1276*4d6fc14bSjoerg struct CacheInfo {
1277*4d6fc14bSjoerg std::string type;
1278*4d6fc14bSjoerg int level;
1279*4d6fc14bSjoerg int size;
1280*4d6fc14bSjoerg int num_sharing;
1281*4d6fc14bSjoerg };
1282*4d6fc14bSjoerg
1283*4d6fc14bSjoerg int num_cpus;
1284*4d6fc14bSjoerg double cycles_per_second;
1285*4d6fc14bSjoerg std::vector<CacheInfo> caches;
1286*4d6fc14bSjoerg bool scaling_enabled;
1287*4d6fc14bSjoerg std::vector<double> load_avg;
1288*4d6fc14bSjoerg
1289*4d6fc14bSjoerg static const CPUInfo& Get();
1290*4d6fc14bSjoerg
1291*4d6fc14bSjoerg private:
1292*4d6fc14bSjoerg CPUInfo();
1293*4d6fc14bSjoerg BENCHMARK_DISALLOW_COPY_AND_ASSIGN(CPUInfo);
1294*4d6fc14bSjoerg };
1295*4d6fc14bSjoerg
1296*4d6fc14bSjoerg //Adding Struct for System Information
1297*4d6fc14bSjoerg struct SystemInfo {
1298*4d6fc14bSjoerg std::string name;
1299*4d6fc14bSjoerg static const SystemInfo& Get();
1300*4d6fc14bSjoerg private:
1301*4d6fc14bSjoerg SystemInfo();
1302*4d6fc14bSjoerg BENCHMARK_DISALLOW_COPY_AND_ASSIGN(SystemInfo);
1303*4d6fc14bSjoerg };
1304*4d6fc14bSjoerg
1305*4d6fc14bSjoerg // Interface for custom benchmark result printers.
1306*4d6fc14bSjoerg // By default, benchmark reports are printed to stdout. However an application
1307*4d6fc14bSjoerg // can control the destination of the reports by calling
1308*4d6fc14bSjoerg // RunSpecifiedBenchmarks and passing it a custom reporter object.
1309*4d6fc14bSjoerg // The reporter object must implement the following interface.
1310*4d6fc14bSjoerg class BenchmarkReporter {
1311*4d6fc14bSjoerg public:
1312*4d6fc14bSjoerg struct Context {
1313*4d6fc14bSjoerg CPUInfo const& cpu_info;
1314*4d6fc14bSjoerg SystemInfo const& sys_info;
1315*4d6fc14bSjoerg // The number of chars in the longest benchmark name.
1316*4d6fc14bSjoerg size_t name_field_width;
1317*4d6fc14bSjoerg static const char* executable_name;
1318*4d6fc14bSjoerg Context();
1319*4d6fc14bSjoerg };
1320*4d6fc14bSjoerg
1321*4d6fc14bSjoerg struct Run {
1322*4d6fc14bSjoerg enum RunType { RT_Iteration, RT_Aggregate };
1323*4d6fc14bSjoerg
RunRun1324*4d6fc14bSjoerg Run()
1325*4d6fc14bSjoerg : run_type(RT_Iteration),
1326*4d6fc14bSjoerg error_occurred(false),
1327*4d6fc14bSjoerg iterations(1),
1328*4d6fc14bSjoerg time_unit(kNanosecond),
1329*4d6fc14bSjoerg real_accumulated_time(0),
1330*4d6fc14bSjoerg cpu_accumulated_time(0),
1331*4d6fc14bSjoerg max_heapbytes_used(0),
1332*4d6fc14bSjoerg complexity(oNone),
1333*4d6fc14bSjoerg complexity_lambda(),
1334*4d6fc14bSjoerg complexity_n(0),
1335*4d6fc14bSjoerg report_big_o(false),
1336*4d6fc14bSjoerg report_rms(false),
1337*4d6fc14bSjoerg counters(),
1338*4d6fc14bSjoerg has_memory_result(false),
1339*4d6fc14bSjoerg allocs_per_iter(0.0),
1340*4d6fc14bSjoerg max_bytes_used(0) {}
1341*4d6fc14bSjoerg
1342*4d6fc14bSjoerg std::string benchmark_name() const;
1343*4d6fc14bSjoerg std::string run_name;
1344*4d6fc14bSjoerg RunType run_type; // is this a measurement, or an aggregate?
1345*4d6fc14bSjoerg std::string aggregate_name;
1346*4d6fc14bSjoerg std::string report_label; // Empty if not set by benchmark.
1347*4d6fc14bSjoerg bool error_occurred;
1348*4d6fc14bSjoerg std::string error_message;
1349*4d6fc14bSjoerg
1350*4d6fc14bSjoerg int64_t iterations;
1351*4d6fc14bSjoerg TimeUnit time_unit;
1352*4d6fc14bSjoerg double real_accumulated_time;
1353*4d6fc14bSjoerg double cpu_accumulated_time;
1354*4d6fc14bSjoerg
1355*4d6fc14bSjoerg // Return a value representing the real time per iteration in the unit
1356*4d6fc14bSjoerg // specified by 'time_unit'.
1357*4d6fc14bSjoerg // NOTE: If 'iterations' is zero the returned value represents the
1358*4d6fc14bSjoerg // accumulated time.
1359*4d6fc14bSjoerg double GetAdjustedRealTime() const;
1360*4d6fc14bSjoerg
1361*4d6fc14bSjoerg // Return a value representing the cpu time per iteration in the unit
1362*4d6fc14bSjoerg // specified by 'time_unit'.
1363*4d6fc14bSjoerg // NOTE: If 'iterations' is zero the returned value represents the
1364*4d6fc14bSjoerg // accumulated time.
1365*4d6fc14bSjoerg double GetAdjustedCPUTime() const;
1366*4d6fc14bSjoerg
1367*4d6fc14bSjoerg // This is set to 0.0 if memory tracing is not enabled.
1368*4d6fc14bSjoerg double max_heapbytes_used;
1369*4d6fc14bSjoerg
1370*4d6fc14bSjoerg // Keep track of arguments to compute asymptotic complexity
1371*4d6fc14bSjoerg BigO complexity;
1372*4d6fc14bSjoerg BigOFunc* complexity_lambda;
1373*4d6fc14bSjoerg int64_t complexity_n;
1374*4d6fc14bSjoerg
1375*4d6fc14bSjoerg // what statistics to compute from the measurements
1376*4d6fc14bSjoerg const std::vector<Statistics>* statistics;
1377*4d6fc14bSjoerg
1378*4d6fc14bSjoerg // Inform print function whether the current run is a complexity report
1379*4d6fc14bSjoerg bool report_big_o;
1380*4d6fc14bSjoerg bool report_rms;
1381*4d6fc14bSjoerg
1382*4d6fc14bSjoerg UserCounters counters;
1383*4d6fc14bSjoerg
1384*4d6fc14bSjoerg // Memory metrics.
1385*4d6fc14bSjoerg bool has_memory_result;
1386*4d6fc14bSjoerg double allocs_per_iter;
1387*4d6fc14bSjoerg int64_t max_bytes_used;
1388*4d6fc14bSjoerg };
1389*4d6fc14bSjoerg
1390*4d6fc14bSjoerg // Construct a BenchmarkReporter with the output stream set to 'std::cout'
1391*4d6fc14bSjoerg // and the error stream set to 'std::cerr'
1392*4d6fc14bSjoerg BenchmarkReporter();
1393*4d6fc14bSjoerg
1394*4d6fc14bSjoerg // Called once for every suite of benchmarks run.
1395*4d6fc14bSjoerg // The parameter "context" contains information that the
1396*4d6fc14bSjoerg // reporter may wish to use when generating its report, for example the
1397*4d6fc14bSjoerg // platform under which the benchmarks are running. The benchmark run is
1398*4d6fc14bSjoerg // never started if this function returns false, allowing the reporter
1399*4d6fc14bSjoerg // to skip runs based on the context information.
1400*4d6fc14bSjoerg virtual bool ReportContext(const Context& context) = 0;
1401*4d6fc14bSjoerg
1402*4d6fc14bSjoerg // Called once for each group of benchmark runs, gives information about
1403*4d6fc14bSjoerg // cpu-time and heap memory usage during the benchmark run. If the group
1404*4d6fc14bSjoerg // of runs contained more than two entries then 'report' contains additional
1405*4d6fc14bSjoerg // elements representing the mean and standard deviation of those runs.
1406*4d6fc14bSjoerg // Additionally if this group of runs was the last in a family of benchmarks
1407*4d6fc14bSjoerg // 'reports' contains additional entries representing the asymptotic
1408*4d6fc14bSjoerg // complexity and RMS of that benchmark family.
1409*4d6fc14bSjoerg virtual void ReportRuns(const std::vector<Run>& report) = 0;
1410*4d6fc14bSjoerg
1411*4d6fc14bSjoerg // Called once and only once after ever group of benchmarks is run and
1412*4d6fc14bSjoerg // reported.
Finalize()1413*4d6fc14bSjoerg virtual void Finalize() {}
1414*4d6fc14bSjoerg
1415*4d6fc14bSjoerg // REQUIRES: The object referenced by 'out' is valid for the lifetime
1416*4d6fc14bSjoerg // of the reporter.
SetOutputStream(std::ostream * out)1417*4d6fc14bSjoerg void SetOutputStream(std::ostream* out) {
1418*4d6fc14bSjoerg assert(out);
1419*4d6fc14bSjoerg output_stream_ = out;
1420*4d6fc14bSjoerg }
1421*4d6fc14bSjoerg
1422*4d6fc14bSjoerg // REQUIRES: The object referenced by 'err' is valid for the lifetime
1423*4d6fc14bSjoerg // of the reporter.
SetErrorStream(std::ostream * err)1424*4d6fc14bSjoerg void SetErrorStream(std::ostream* err) {
1425*4d6fc14bSjoerg assert(err);
1426*4d6fc14bSjoerg error_stream_ = err;
1427*4d6fc14bSjoerg }
1428*4d6fc14bSjoerg
GetOutputStream()1429*4d6fc14bSjoerg std::ostream& GetOutputStream() const { return *output_stream_; }
1430*4d6fc14bSjoerg
GetErrorStream()1431*4d6fc14bSjoerg std::ostream& GetErrorStream() const { return *error_stream_; }
1432*4d6fc14bSjoerg
1433*4d6fc14bSjoerg virtual ~BenchmarkReporter();
1434*4d6fc14bSjoerg
1435*4d6fc14bSjoerg // Write a human readable string to 'out' representing the specified
1436*4d6fc14bSjoerg // 'context'.
1437*4d6fc14bSjoerg // REQUIRES: 'out' is non-null.
1438*4d6fc14bSjoerg static void PrintBasicContext(std::ostream* out, Context const& context);
1439*4d6fc14bSjoerg
1440*4d6fc14bSjoerg private:
1441*4d6fc14bSjoerg std::ostream* output_stream_;
1442*4d6fc14bSjoerg std::ostream* error_stream_;
1443*4d6fc14bSjoerg };
1444*4d6fc14bSjoerg
1445*4d6fc14bSjoerg // Simple reporter that outputs benchmark data to the console. This is the
1446*4d6fc14bSjoerg // default reporter used by RunSpecifiedBenchmarks().
1447*4d6fc14bSjoerg class ConsoleReporter : public BenchmarkReporter {
1448*4d6fc14bSjoerg public:
1449*4d6fc14bSjoerg enum OutputOptions {
1450*4d6fc14bSjoerg OO_None = 0,
1451*4d6fc14bSjoerg OO_Color = 1,
1452*4d6fc14bSjoerg OO_Tabular = 2,
1453*4d6fc14bSjoerg OO_ColorTabular = OO_Color | OO_Tabular,
1454*4d6fc14bSjoerg OO_Defaults = OO_ColorTabular
1455*4d6fc14bSjoerg };
1456*4d6fc14bSjoerg explicit ConsoleReporter(OutputOptions opts_ = OO_Defaults)
output_options_(opts_)1457*4d6fc14bSjoerg : output_options_(opts_),
1458*4d6fc14bSjoerg name_field_width_(0),
1459*4d6fc14bSjoerg prev_counters_(),
1460*4d6fc14bSjoerg printed_header_(false) {}
1461*4d6fc14bSjoerg
1462*4d6fc14bSjoerg virtual bool ReportContext(const Context& context);
1463*4d6fc14bSjoerg virtual void ReportRuns(const std::vector<Run>& reports);
1464*4d6fc14bSjoerg
1465*4d6fc14bSjoerg protected:
1466*4d6fc14bSjoerg virtual void PrintRunData(const Run& report);
1467*4d6fc14bSjoerg virtual void PrintHeader(const Run& report);
1468*4d6fc14bSjoerg
1469*4d6fc14bSjoerg OutputOptions output_options_;
1470*4d6fc14bSjoerg size_t name_field_width_;
1471*4d6fc14bSjoerg UserCounters prev_counters_;
1472*4d6fc14bSjoerg bool printed_header_;
1473*4d6fc14bSjoerg };
1474*4d6fc14bSjoerg
1475*4d6fc14bSjoerg class JSONReporter : public BenchmarkReporter {
1476*4d6fc14bSjoerg public:
JSONReporter()1477*4d6fc14bSjoerg JSONReporter() : first_report_(true) {}
1478*4d6fc14bSjoerg virtual bool ReportContext(const Context& context);
1479*4d6fc14bSjoerg virtual void ReportRuns(const std::vector<Run>& reports);
1480*4d6fc14bSjoerg virtual void Finalize();
1481*4d6fc14bSjoerg
1482*4d6fc14bSjoerg private:
1483*4d6fc14bSjoerg void PrintRunData(const Run& report);
1484*4d6fc14bSjoerg
1485*4d6fc14bSjoerg bool first_report_;
1486*4d6fc14bSjoerg };
1487*4d6fc14bSjoerg
1488*4d6fc14bSjoerg class BENCHMARK_DEPRECATED_MSG("The CSV Reporter will be removed in a future release")
1489*4d6fc14bSjoerg CSVReporter : public BenchmarkReporter {
1490*4d6fc14bSjoerg public:
CSVReporter()1491*4d6fc14bSjoerg CSVReporter() : printed_header_(false) {}
1492*4d6fc14bSjoerg virtual bool ReportContext(const Context& context);
1493*4d6fc14bSjoerg virtual void ReportRuns(const std::vector<Run>& reports);
1494*4d6fc14bSjoerg
1495*4d6fc14bSjoerg private:
1496*4d6fc14bSjoerg void PrintRunData(const Run& report);
1497*4d6fc14bSjoerg
1498*4d6fc14bSjoerg bool printed_header_;
1499*4d6fc14bSjoerg std::set<std::string> user_counter_names_;
1500*4d6fc14bSjoerg };
1501*4d6fc14bSjoerg
1502*4d6fc14bSjoerg // If a MemoryManager is registered, it can be used to collect and report
1503*4d6fc14bSjoerg // allocation metrics for a run of the benchmark.
1504*4d6fc14bSjoerg class MemoryManager {
1505*4d6fc14bSjoerg public:
1506*4d6fc14bSjoerg struct Result {
ResultResult1507*4d6fc14bSjoerg Result() : num_allocs(0), max_bytes_used(0) {}
1508*4d6fc14bSjoerg
1509*4d6fc14bSjoerg // The number of allocations made in total between Start and Stop.
1510*4d6fc14bSjoerg int64_t num_allocs;
1511*4d6fc14bSjoerg
1512*4d6fc14bSjoerg // The peak memory use between Start and Stop.
1513*4d6fc14bSjoerg int64_t max_bytes_used;
1514*4d6fc14bSjoerg };
1515*4d6fc14bSjoerg
~MemoryManager()1516*4d6fc14bSjoerg virtual ~MemoryManager() {}
1517*4d6fc14bSjoerg
1518*4d6fc14bSjoerg // Implement this to start recording allocation information.
1519*4d6fc14bSjoerg virtual void Start() = 0;
1520*4d6fc14bSjoerg
1521*4d6fc14bSjoerg // Implement this to stop recording and fill out the given Result structure.
1522*4d6fc14bSjoerg virtual void Stop(Result* result) = 0;
1523*4d6fc14bSjoerg };
1524*4d6fc14bSjoerg
GetTimeUnitString(TimeUnit unit)1525*4d6fc14bSjoerg inline const char* GetTimeUnitString(TimeUnit unit) {
1526*4d6fc14bSjoerg switch (unit) {
1527*4d6fc14bSjoerg case kMillisecond:
1528*4d6fc14bSjoerg return "ms";
1529*4d6fc14bSjoerg case kMicrosecond:
1530*4d6fc14bSjoerg return "us";
1531*4d6fc14bSjoerg case kNanosecond:
1532*4d6fc14bSjoerg return "ns";
1533*4d6fc14bSjoerg }
1534*4d6fc14bSjoerg BENCHMARK_UNREACHABLE();
1535*4d6fc14bSjoerg }
1536*4d6fc14bSjoerg
GetTimeUnitMultiplier(TimeUnit unit)1537*4d6fc14bSjoerg inline double GetTimeUnitMultiplier(TimeUnit unit) {
1538*4d6fc14bSjoerg switch (unit) {
1539*4d6fc14bSjoerg case kMillisecond:
1540*4d6fc14bSjoerg return 1e3;
1541*4d6fc14bSjoerg case kMicrosecond:
1542*4d6fc14bSjoerg return 1e6;
1543*4d6fc14bSjoerg case kNanosecond:
1544*4d6fc14bSjoerg return 1e9;
1545*4d6fc14bSjoerg }
1546*4d6fc14bSjoerg BENCHMARK_UNREACHABLE();
1547*4d6fc14bSjoerg }
1548*4d6fc14bSjoerg
1549*4d6fc14bSjoerg } // namespace benchmark
1550*4d6fc14bSjoerg
1551*4d6fc14bSjoerg #endif // BENCHMARK_BENCHMARK_H_
1552