Skip to content

Commit

Permalink
Add BENCHMARK_TEMPLATE[12]_CAPTURE, fusion of BENCHMARK_CAPTURE a…
Browse files Browse the repository at this point in the history
…nd `BENCHMARK_TEMPLATE`

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 avoid this helper.
  • Loading branch information
LebedevRI committed Jan 29, 2024
1 parent 30a37e1 commit 986029e
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 0 deletions.
26 changes: 26 additions & 0 deletions docs/user_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@

[Templated Benchmarks](#templated-benchmarks)

[Templated Benchmarks that take arguments](#templated-benchmarks-with-arguments)

[Fixtures](#fixtures)

[Custom Counters](#custom-counters)
Expand Down Expand Up @@ -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
Expand Down
30 changes: 30 additions & 0 deletions include/benchmark/benchmark.h
Original file line number Diff line number Diff line change
Expand Up @@ -1560,6 +1560,36 @@ 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_PRIVATE_DECLARE(func) = \
(::benchmark::internal::RegisterBenchmarkInternal( \
new ::benchmark::internal::FunctionBenchmark( \
#func "<" #a ">" \
"/" #test_case_name, \
[](::benchmark::State& st) { func<a>(st, __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: \
Expand Down
24 changes: 24 additions & 0 deletions test/benchmark_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <sstream>
#include <string>
#include <thread>
#include <type_traits>
#include <utility>
#include <vector>

Expand Down Expand Up @@ -226,6 +227,29 @@ 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);

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);

#endif // BENCHMARK_HAS_CXX11

static void BM_DenseThreadRanges(benchmark::State& st) {
Expand Down

0 comments on commit 986029e

Please sign in to comment.