• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Created by Joachim on 16/04/2019.
3  *  Adapted from donated nonius code.
4  *
5  *  Distributed under the Boost Software License, Version 1.0. (See accompanying
6  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7  */
8 
9 // Run a function for a minimum amount of time
10 
11 #ifndef TWOBLUECUBES_CATCH_RUN_FOR_AT_LEAST_HPP_INCLUDED
12 #define TWOBLUECUBES_CATCH_RUN_FOR_AT_LEAST_HPP_INCLUDED
13 
14 #include "../catch_clock.hpp"
15 #include "../catch_chronometer.hpp"
16 #include "catch_measure.hpp"
17 #include "catch_complete_invoke.hpp"
18 #include "catch_timing.hpp"
19 #include "../../catch_meta.hpp"
20 
21 #include <utility>
22 #include <type_traits>
23 
24 namespace Catch {
25     namespace Benchmark {
26         namespace Detail {
27             template <typename Clock, typename Fun>
measure_one(Fun && fun,int iters,std::false_type)28             TimingOf<Clock, Fun(int)> measure_one(Fun&& fun, int iters, std::false_type) {
29                 return Detail::measure<Clock>(fun, iters);
30             }
31             template <typename Clock, typename Fun>
measure_one(Fun && fun,int iters,std::true_type)32             TimingOf<Clock, Fun(Chronometer)> measure_one(Fun&& fun, int iters, std::true_type) {
33                 Detail::ChronometerModel<Clock> meter;
34                 auto&& result = Detail::complete_invoke(fun, Chronometer(meter, iters));
35 
36                 return { meter.elapsed(), std::move(result), iters };
37             }
38 
39             template <typename Clock, typename Fun>
40             using run_for_at_least_argument_t = typename std::conditional<is_callable<Fun(Chronometer)>::value, Chronometer, int>::type;
41 
42             struct optimized_away_error : std::exception {
whatCatch::Benchmark::Detail::optimized_away_error43                 const char* what() const noexcept override {
44                     return "could not measure benchmark, maybe it was optimized away";
45                 }
46             };
47 
48             template <typename Clock, typename Fun>
run_for_at_least(ClockDuration<Clock> how_long,int seed,Fun && fun)49             TimingOf<Clock, Fun(run_for_at_least_argument_t<Clock, Fun>)> run_for_at_least(ClockDuration<Clock> how_long, int seed, Fun&& fun) {
50                 auto iters = seed;
51                 while (iters < (1 << 30)) {
52                     auto&& Timing = measure_one<Clock>(fun, iters, is_callable<Fun(Chronometer)>());
53 
54                     if (Timing.elapsed >= how_long) {
55                         return { Timing.elapsed, std::move(Timing.result), iters };
56                     }
57                     iters *= 2;
58                 }
59                 throw optimized_away_error{};
60             }
61         } // namespace Detail
62     } // namespace Benchmark
63 } // namespace Catch
64 
65 #endif // TWOBLUECUBES_CATCH_RUN_FOR_AT_LEAST_HPP_INCLUDED
66