initial commit
[benchmarks.git] / harness.h
1 #pragma once
2
3 #include <chrono>
4 #include <cstdint>
5 #include <optional>
6 #include <type_traits>
7 #include <utility>
8
9 struct Config final
10 {
11 std::optional<std::uint32_t> thread_count;
12 std::optional<std::uint64_t> iteration_count;
13 };
14
15 template <typename Fn, typename Input,
16 typename Output = std::invoke_result_t<Fn, Input>>
17 class BenchHarness;
18
19 class BenchHarnessBase
20 {
21 template <typename Fn, typename Input, typename Output>
22 friend class BenchHarness;
23
24 private:
25 void base_run(Config config,
26 void (*fn)(BenchHarnessBase *bench_harness_base,
27 std::uint64_t iteration_count));
28 };
29
30 template <typename Fn, typename Input>
31 class BenchHarness<Fn, Input, std::invoke_result_t<Fn, Input>> final
32 : private BenchHarnessBase
33 {
34 private:
35 Fn fn;
36
37 public:
38 void run(Config config)
39 {
40 base_run(config, [](BenchHarnessBase *bench_harness_base,
41 std::uint64_t iteration_count) {
42 auto &fn = static_cast<BenchHarness *>(bench_harness_base)->fn;
43 for (std::uint64_t i = 0; i < iteration_count; i++)
44 {
45 Input input;
46
47 // optimization barrier
48 asm("" : : "r"(std::addressof(input)) : "memory");
49
50 auto output = fn(input);
51
52 // optimization barrier
53 asm("" : : "r"(std::addressof(output)) : "memory");
54 }
55 });
56 }
57 };