mirror of https://github.com/google/benchmark.git
Add `BENCHMARK_TEMPLATE[12]_CAPTURE`, fusion of `BENCHMARK_CAPTURE` and `BENCHMARK_TEMPLATE` (#1747)
Test coverage isn't great, but not worse than the existing one. You'd think `BENCHMARK_CAPTURE` would suffice, but you can't pass `func<targs>` to it (due to the `<` and `>`), and when passing `(func<targs>)` we get issues with brackets. So i'm not sure if we can fully avoid this helper. That being said, if there is only a single template argument, `BENCHMARK_CAPTURE()` works fine if we avoid using function name.
This commit is contained in:
parent
30a37e1b0b
commit
e990563876
|
@ -28,6 +28,8 @@
|
|||
|
||||
[Templated Benchmarks](#templated-benchmarks)
|
||||
|
||||
[Templated Benchmarks that take arguments](#templated-benchmarks-with-arguments)
|
||||
|
||||
[Fixtures](#fixtures)
|
||||
|
||||
[Custom Counters](#custom-counters)
|
||||
|
@ -574,6 +576,30 @@ Three macros are provided for adding benchmark templates.
|
|||
#define BENCHMARK_TEMPLATE2(func, arg1, arg2)
|
||||
```
|
||||
|
||||
<a name="templated-benchmarks-with-arguments" />
|
||||
|
||||
## Templated Benchmarks that take arguments
|
||||
|
||||
Sometimes there is a need to template benchmarks, and provide arguments to them.
|
||||
|
||||
```c++
|
||||
template <class Q> void BM_Sequential_With_Step(benchmark::State& state, int step) {
|
||||
Q q;
|
||||
typename Q::value_type v;
|
||||
for (auto _ : state) {
|
||||
for (int i = state.range(0); i-=step; )
|
||||
q.push(v);
|
||||
for (int e = state.range(0); e-=step; )
|
||||
q.Wait(&v);
|
||||
}
|
||||
// actually messages, not bytes:
|
||||
state.SetBytesProcessed(
|
||||
static_cast<int64_t>(state.iterations())*state.range(0));
|
||||
}
|
||||
|
||||
BENCHMARK_TEMPLATE1_CAPTURE(BM_Sequential, WaitQueue<int>, Step1, 1)->Range(1<<0, 1<<10);
|
||||
```
|
||||
|
||||
<a name="fixtures" />
|
||||
|
||||
## Fixtures
|
||||
|
|
|
@ -1523,7 +1523,7 @@ class Fixture : public internal::Benchmark {
|
|||
// /* 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_PRIVATE_DECLARE(_benchmark_) = \
|
||||
(::benchmark::internal::RegisterBenchmarkInternal( \
|
||||
new ::benchmark::internal::FunctionBenchmark( \
|
||||
#func "/" #test_case_name, \
|
||||
|
@ -1560,6 +1560,31 @@ class Fixture : public internal::Benchmark {
|
|||
#define BENCHMARK_TEMPLATE(n, a) BENCHMARK_TEMPLATE1(n, a)
|
||||
#endif
|
||||
|
||||
#ifdef BENCHMARK_HAS_CXX11
|
||||
// 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( \
|
||||
new ::benchmark::internal::FunctionBenchmark( \
|
||||
#func "<" #a "," #b ">" \
|
||||
"/" #test_case_name, \
|
||||
[](::benchmark::State& st) { func<a, b>(st, __VA_ARGS__); })))
|
||||
#endif // BENCHMARK_HAS_CXX11
|
||||
|
||||
#define BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \
|
||||
class BaseClass##_##Method##_Benchmark : public BaseClass { \
|
||||
public: \
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <sstream>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
|
@ -226,6 +227,31 @@ void BM_non_template_args(benchmark::State& state, int, double) {
|
|||
}
|
||||
BENCHMARK_CAPTURE(BM_non_template_args, basic_test, 0, 0);
|
||||
|
||||
template <class T, class U, class... ExtraArgs>
|
||||
void BM_template2_capture(benchmark::State& state, ExtraArgs&&... extra_args) {
|
||||
static_assert(std::is_same<T, void>::value, "");
|
||||
static_assert(std::is_same<U, char*>::value, "");
|
||||
static_assert(std::is_same<ExtraArgs..., unsigned int>::value, "");
|
||||
unsigned int dummy[sizeof...(ExtraArgs)] = {extra_args...};
|
||||
assert(dummy[0] == 42);
|
||||
for (auto _ : state) {
|
||||
}
|
||||
}
|
||||
BENCHMARK_TEMPLATE2_CAPTURE(BM_template2_capture, void, char*, foo, 42U);
|
||||
BENCHMARK_CAPTURE((BM_template2_capture<void, char*>), foo, 42U);
|
||||
|
||||
template <class T, class... ExtraArgs>
|
||||
void BM_template1_capture(benchmark::State& state, ExtraArgs&&... extra_args) {
|
||||
static_assert(std::is_same<T, void>::value, "");
|
||||
static_assert(std::is_same<ExtraArgs..., unsigned long>::value, "");
|
||||
unsigned long dummy[sizeof...(ExtraArgs)] = {extra_args...};
|
||||
assert(dummy[0] == 24);
|
||||
for (auto _ : state) {
|
||||
}
|
||||
}
|
||||
BENCHMARK_TEMPLATE1_CAPTURE(BM_template1_capture, void, foo, 24UL);
|
||||
BENCHMARK_CAPTURE(BM_template1_capture<void>, foo, 24UL);
|
||||
|
||||
#endif // BENCHMARK_HAS_CXX11
|
||||
|
||||
static void BM_DenseThreadRanges(benchmark::State& st) {
|
||||
|
|
Loading…
Reference in New Issue