Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:02:48

0001 
0002 //              Copyright Catch2 Authors
0003 // Distributed under the Boost Software License, Version 1.0.
0004 //   (See accompanying file LICENSE.txt or copy at
0005 //        https://www.boost.org/LICENSE_1_0.txt)
0006 
0007 // SPDX-License-Identifier: BSL-1.0
0008 // Adapted from donated nonius code.
0009 
0010 #ifndef CATCH_BENCHMARK_HPP_INCLUDED
0011 #define CATCH_BENCHMARK_HPP_INCLUDED
0012 
0013 #include <catch2/catch_user_config.hpp>
0014 #include <catch2/internal/catch_compiler_capabilities.hpp>
0015 #include <catch2/internal/catch_context.hpp>
0016 #include <catch2/internal/catch_move_and_forward.hpp>
0017 #include <catch2/internal/catch_test_failure_exception.hpp>
0018 #include <catch2/internal/catch_unique_name.hpp>
0019 #include <catch2/interfaces/catch_interfaces_capture.hpp>
0020 #include <catch2/interfaces/catch_interfaces_config.hpp>
0021 #include <catch2/interfaces/catch_interfaces_registry_hub.hpp>
0022 #include <catch2/benchmark/detail/catch_benchmark_stats.hpp>
0023 #include <catch2/benchmark/catch_clock.hpp>
0024 #include <catch2/benchmark/catch_environment.hpp>
0025 #include <catch2/benchmark/catch_execution_plan.hpp>
0026 #include <catch2/benchmark/detail/catch_estimate_clock.hpp>
0027 #include <catch2/benchmark/detail/catch_analyse.hpp>
0028 #include <catch2/benchmark/detail/catch_benchmark_function.hpp>
0029 #include <catch2/benchmark/detail/catch_run_for_at_least.hpp>
0030 
0031 #include <algorithm>
0032 #include <chrono>
0033 #include <exception>
0034 #include <functional>
0035 #include <string>
0036 #include <vector>
0037 #include <cmath>
0038 
0039 namespace Catch {
0040     namespace Benchmark {
0041         struct Benchmark {
0042             Benchmark(std::string&& benchmarkName)
0043                 : name(CATCH_MOVE(benchmarkName)) {}
0044 
0045             template <class FUN>
0046             Benchmark(std::string&& benchmarkName , FUN &&func)
0047                 : fun(CATCH_MOVE(func)), name(CATCH_MOVE(benchmarkName)) {}
0048 
0049             template <typename Clock>
0050             ExecutionPlan<FloatDuration<Clock>> prepare(const IConfig &cfg, Environment<FloatDuration<Clock>> env) const {
0051                 auto min_time = env.clock_resolution.mean * Detail::minimum_ticks;
0052                 auto run_time = std::max(min_time, std::chrono::duration_cast<decltype(min_time)>(cfg.benchmarkWarmupTime()));
0053                 auto&& test = Detail::run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(run_time), 1, fun);
0054                 int new_iters = static_cast<int>(std::ceil(min_time * test.iterations / test.elapsed));
0055                 return { new_iters, test.elapsed / test.iterations * new_iters * cfg.benchmarkSamples(), fun, std::chrono::duration_cast<FloatDuration<Clock>>(cfg.benchmarkWarmupTime()), Detail::warmup_iterations };
0056             }
0057 
0058             template <typename Clock = default_clock>
0059             void run() {
0060                 auto const* cfg = getCurrentContext().getConfig();
0061 
0062                 auto env = Detail::measure_environment<Clock>();
0063 
0064                 getResultCapture().benchmarkPreparing(name);
0065                 CATCH_TRY{
0066                     auto plan = user_code([&] {
0067                         return prepare<Clock>(*cfg, env);
0068                     });
0069 
0070                     BenchmarkInfo info {
0071                         CATCH_MOVE(name),
0072                         plan.estimated_duration.count(),
0073                         plan.iterations_per_sample,
0074                         cfg->benchmarkSamples(),
0075                         cfg->benchmarkResamples(),
0076                         env.clock_resolution.mean.count(),
0077                         env.clock_cost.mean.count()
0078                     };
0079 
0080                     getResultCapture().benchmarkStarting(info);
0081 
0082                     auto samples = user_code([&] {
0083                         return plan.template run<Clock>(*cfg, env);
0084                     });
0085 
0086                     auto analysis = Detail::analyse(*cfg, env, samples.begin(), samples.end());
0087                     BenchmarkStats<FloatDuration<Clock>> stats{ CATCH_MOVE(info), CATCH_MOVE(analysis.samples), analysis.mean, analysis.standard_deviation, analysis.outliers, analysis.outlier_variance };
0088                     getResultCapture().benchmarkEnded(stats);
0089                 } CATCH_CATCH_ANON (TestFailureException const&) {
0090                     getResultCapture().benchmarkFailed("Benchmark failed due to failed assertion"_sr);
0091                 } CATCH_CATCH_ALL{
0092                     getResultCapture().benchmarkFailed(translateActiveException());
0093                     // We let the exception go further up so that the
0094                     // test case is marked as failed.
0095                     std::rethrow_exception(std::current_exception());
0096                 }
0097             }
0098 
0099             // sets lambda to be used in fun *and* executes benchmark!
0100             template <typename Fun, std::enable_if_t<!Detail::is_related<Fun, Benchmark>::value, int> = 0>
0101                 Benchmark & operator=(Fun func) {
0102                 auto const* cfg = getCurrentContext().getConfig();
0103                 if (!cfg->skipBenchmarks()) {
0104                     fun = Detail::BenchmarkFunction(func);
0105                     run();
0106                 }
0107                 return *this;
0108             }
0109 
0110             explicit operator bool() {
0111                 return true;
0112             }
0113 
0114         private:
0115             Detail::BenchmarkFunction fun;
0116             std::string name;
0117         };
0118     }
0119 } // namespace Catch
0120 
0121 #define INTERNAL_CATCH_GET_1_ARG(arg1, arg2, ...) arg1
0122 #define INTERNAL_CATCH_GET_2_ARG(arg1, arg2, ...) arg2
0123 
0124 #define INTERNAL_CATCH_BENCHMARK(BenchmarkName, name, benchmarkIndex)\
0125     if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \
0126         BenchmarkName = [&](int benchmarkIndex)
0127 
0128 #define INTERNAL_CATCH_BENCHMARK_ADVANCED(BenchmarkName, name)\
0129     if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \
0130         BenchmarkName = [&]
0131 
0132 #if defined(CATCH_CONFIG_PREFIX_ALL)
0133 
0134 #define CATCH_BENCHMARK(...) \
0135     INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_BENCHMARK_), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,))
0136 #define CATCH_BENCHMARK_ADVANCED(name) \
0137     INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_BENCHMARK_), name)
0138 
0139 #else
0140 
0141 #define BENCHMARK(...) \
0142     INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_BENCHMARK_), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,))
0143 #define BENCHMARK_ADVANCED(name) \
0144     INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_BENCHMARK_), name)
0145 
0146 #endif
0147 
0148 #endif // CATCH_BENCHMARK_HPP_INCLUDED