summaryrefslogtreecommitdiff
path: root/include/internal/benchmark/detail/catch_run_for_at_least.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'include/internal/benchmark/detail/catch_run_for_at_least.hpp')
-rw-r--r--include/internal/benchmark/detail/catch_run_for_at_least.hpp65
1 files changed, 65 insertions, 0 deletions
diff --git a/include/internal/benchmark/detail/catch_run_for_at_least.hpp b/include/internal/benchmark/detail/catch_run_for_at_least.hpp
new file mode 100644
index 00000000..a41c6b46
--- /dev/null
+++ b/include/internal/benchmark/detail/catch_run_for_at_least.hpp
@@ -0,0 +1,65 @@
+/*
+ * Created by Joachim on 16/04/2019.
+ * Adapted from donated nonius code.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+// Run a function for a minimum amount of time
+
+#ifndef TWOBLUECUBES_CATCH_RUN_FOR_AT_LEAST_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_RUN_FOR_AT_LEAST_HPP_INCLUDED
+
+#include "../catch_clock.hpp"
+#include "../catch_chronometer.hpp"
+#include "catch_measure.hpp"
+#include "catch_complete_invoke.hpp"
+#include "catch_timing.hpp"
+#include "../../catch_meta.hpp"
+
+#include <utility>
+#include <type_traits>
+
+namespace Catch {
+ namespace Benchmark {
+ namespace Detail {
+ template <typename Clock, typename Fun>
+ TimingOf<Clock, Fun(int)> measure_one(Fun&& fun, int iters, std::false_type) {
+ return Detail::measure<Clock>(fun, iters);
+ }
+ template <typename Clock, typename Fun>
+ TimingOf<Clock, Fun(Chronometer)> measure_one(Fun&& fun, int iters, std::true_type) {
+ Detail::ChronometerModel<Clock> meter;
+ auto&& result = Detail::complete_invoke(fun, Chronometer(meter, iters));
+
+ return { meter.elapsed(), std::move(result), iters };
+ }
+
+ template <typename Clock, typename Fun>
+ using run_for_at_least_argument_t = typename std::conditional<is_callable<Fun(Chronometer)>::value, Chronometer, int>::type;
+
+ struct optimized_away_error : std::exception {
+ const char* what() const noexcept override {
+ return "could not measure benchmark, maybe it was optimized away";
+ }
+ };
+
+ template <typename Clock, typename Fun>
+ TimingOf<Clock, Fun(run_for_at_least_argument_t<Clock, Fun>)> run_for_at_least(ClockDuration<Clock> how_long, int seed, Fun&& fun) {
+ auto iters = seed;
+ while (iters < (1 << 30)) {
+ auto&& Timing = measure_one<Clock>(fun, iters, is_callable<Fun(Chronometer)>());
+
+ if (Timing.elapsed >= how_long) {
+ return { Timing.elapsed, std::move(Timing.result), iters };
+ }
+ iters *= 2;
+ }
+ throw optimized_away_error{};
+ }
+ } // namespace Detail
+ } // namespace Benchmark
+} // namespace Catch
+
+#endif // TWOBLUECUBES_CATCH_RUN_FOR_AT_LEAST_HPP_INCLUDED