Allow benchmarks to take arbitrary arguments. (#221)

* Add lambda benchmarks

* Remove lambda capture since the lambda is not at a block scope

* Remove LambdaBenchmark helper since FunctionBenchmark can be used with non-capturing lambas

* Add lambda benchmarks

* Remove lambda capture since the lambda is not at a block scope

* Remove LambdaBenchmark helper since FunctionBenchmark can be used with non-capturing lambas

* Add more docs for BENCHMARK_CAPTURE.

* Fix use of misnamed parameter

* Guard BENCHMARK_CAPTURE tests against non-c++11 compilers

* Move tests out of basic_test.cc
This commit is contained in:
Eric 2016-05-27 13:37:10 -06:00 committed by Dominic Hamon
parent 5686bf1b38
commit 238e558fdb
3 changed files with 60 additions and 0 deletions

View File

@ -176,6 +176,26 @@ Three macros are provided for adding benchmark templates.
#define BENCHMARK_TEMPLATE2(func, arg1, arg2) #define BENCHMARK_TEMPLATE2(func, arg1, arg2)
``` ```
## Passing arbitrary arguments to a benchmark
In C++11 it is possible to define a benchmark that takes an arbitrary number
of extra arguments. The `BENCHMARK_CAPTURE(func, test_case_name, ...args)`
macro creates a benchmark that invokes `func` with the `benchmark::State` as
the first argument followed by the specified `args...`.
The `test_case_name` is appended to the name of the benchmark and
should describe the values passed.
```c++
template <class ...ExtraArgs>`
void BM_takes_args(benchmark::State& state, ExtraArgs&&... extra_args) {
[...]
}
// Registers a benchmark named "BM_takes_args/int_string_test` that passes
// the specified values to `extra_args`.
BENCHMARK_CAPTURE(BM_takes_args, int_string_test, 42, std::string("abc"));
```
Note that elements of `...args` may refer to global variables. Users should
avoid modifying global state inside of a benchmark.
### Multithreaded benchmarks ### Multithreaded benchmarks
In a multithreaded test (benchmark invoked by multiple threads simultaneously), In a multithreaded test (benchmark invoked by multiple threads simultaneously),
it is guaranteed that none of the threads will start until all have called it is guaranteed that none of the threads will start until all have called

View File

@ -650,6 +650,28 @@ protected:
#define BENCHMARK_RANGE2(n, l1, h1, l2, h2) \ #define BENCHMARK_RANGE2(n, l1, h1, l2, h2) \
BENCHMARK(n)->RangePair((l1), (h1), (l2), (h2)) BENCHMARK(n)->RangePair((l1), (h1), (l2), (h2))
#if __cplusplus >= 201103L
// 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(func) = \
(::benchmark::internal::RegisterBenchmarkInternal( \
new ::benchmark::internal::FunctionBenchmark( \
#func "/" #test_case_name, \
[](::benchmark::State& st) { func(st, __VA_ARGS__); })))
#endif // __cplusplus >= 11
// This will register a benchmark for a templatized function. For example: // This will register a benchmark for a templatized function. For example:
// //
// template<int arg> // template<int arg>

View File

@ -16,6 +16,7 @@
#include <vector> #include <vector>
#include <chrono> #include <chrono>
#include <thread> #include <thread>
#include <utility>
#if defined(__GNUC__) #if defined(__GNUC__)
# define BENCHMARK_NOINLINE __attribute__((noinline)) # define BENCHMARK_NOINLINE __attribute__((noinline))
@ -202,5 +203,22 @@ static void BM_ManualTiming(benchmark::State& state) {
BENCHMARK(BM_ManualTiming)->Range(1, 1 << 14)->UseRealTime(); BENCHMARK(BM_ManualTiming)->Range(1, 1 << 14)->UseRealTime();
BENCHMARK(BM_ManualTiming)->Range(1, 1 << 14)->UseManualTime(); BENCHMARK(BM_ManualTiming)->Range(1, 1 << 14)->UseManualTime();
#if __cplusplus >= 201103L
template <class ...Args>
void BM_with_args(benchmark::State& state, Args&&...) {
while (state.KeepRunning()) {}
}
BENCHMARK_CAPTURE(BM_with_args, int_test, 42, 43, 44);
BENCHMARK_CAPTURE(BM_with_args, string_and_pair_test,
std::string("abc"), std::pair<int, double>(42, 3.8));
void BM_non_template_args(benchmark::State& state, int, double) {
while(state.KeepRunning()) {}
}
BENCHMARK_CAPTURE(BM_non_template_args, basic_test, 0, 0);
#endif // __cplusplus >= 201103L
BENCHMARK_MAIN() BENCHMARK_MAIN()