File indexing completed on 2025-09-16 08:52:10
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef CATCH_ESTIMATE_CLOCK_HPP_INCLUDED
0011 #define CATCH_ESTIMATE_CLOCK_HPP_INCLUDED
0012
0013 #include <catch2/benchmark/catch_clock.hpp>
0014 #include <catch2/benchmark/catch_environment.hpp>
0015 #include <catch2/benchmark/detail/catch_stats.hpp>
0016 #include <catch2/benchmark/detail/catch_measure.hpp>
0017 #include <catch2/benchmark/detail/catch_run_for_at_least.hpp>
0018 #include <catch2/benchmark/catch_clock.hpp>
0019 #include <catch2/internal/catch_unique_ptr.hpp>
0020
0021 #include <algorithm>
0022 #include <vector>
0023 #include <cmath>
0024
0025 namespace Catch {
0026 namespace Benchmark {
0027 namespace Detail {
0028 template <typename Clock>
0029 std::vector<double> resolution(int k) {
0030 const size_t points = static_cast<size_t>( k + 1 );
0031
0032
0033 std::vector<TimePoint<Clock>> times(points);
0034 for ( auto& time : times ) {
0035 time = Clock::now();
0036 }
0037
0038 std::vector<double> deltas;
0039 deltas.reserve(static_cast<size_t>(k));
0040 for ( size_t idx = 1; idx < points; ++idx ) {
0041 deltas.push_back( static_cast<double>(
0042 ( times[idx] - times[idx - 1] ).count() ) );
0043 }
0044
0045 return deltas;
0046 }
0047
0048 constexpr auto warmup_iterations = 10000;
0049 constexpr auto warmup_time = std::chrono::milliseconds(100);
0050 constexpr auto minimum_ticks = 1000;
0051 constexpr auto warmup_seed = 10000;
0052 constexpr auto clock_resolution_estimation_time = std::chrono::milliseconds(500);
0053 constexpr auto clock_cost_estimation_time_limit = std::chrono::seconds(1);
0054 constexpr auto clock_cost_estimation_tick_limit = 100000;
0055 constexpr auto clock_cost_estimation_time = std::chrono::milliseconds(10);
0056 constexpr auto clock_cost_estimation_iterations = 10000;
0057
0058 template <typename Clock>
0059 int warmup() {
0060 return run_for_at_least<Clock>(warmup_time, warmup_seed, &resolution<Clock>)
0061 .iterations;
0062 }
0063 template <typename Clock>
0064 EnvironmentEstimate estimate_clock_resolution(int iterations) {
0065 auto r = run_for_at_least<Clock>(clock_resolution_estimation_time, iterations, &resolution<Clock>)
0066 .result;
0067 return {
0068 FDuration(mean(r.data(), r.data() + r.size())),
0069 classify_outliers(r.data(), r.data() + r.size()),
0070 };
0071 }
0072 template <typename Clock>
0073 EnvironmentEstimate estimate_clock_cost(FDuration resolution) {
0074 auto time_limit = (std::min)(
0075 resolution * clock_cost_estimation_tick_limit,
0076 FDuration(clock_cost_estimation_time_limit));
0077 auto time_clock = [](int k) {
0078 return Detail::measure<Clock>([k] {
0079 for (int i = 0; i < k; ++i) {
0080 volatile auto ignored = Clock::now();
0081 (void)ignored;
0082 }
0083 }).elapsed;
0084 };
0085 time_clock(1);
0086 int iters = clock_cost_estimation_iterations;
0087 auto&& r = run_for_at_least<Clock>(clock_cost_estimation_time, iters, time_clock);
0088 std::vector<double> times;
0089 int nsamples = static_cast<int>(std::ceil(time_limit / r.elapsed));
0090 times.reserve(static_cast<size_t>(nsamples));
0091 for ( int s = 0; s < nsamples; ++s ) {
0092 times.push_back( static_cast<double>(
0093 ( time_clock( r.iterations ) / r.iterations )
0094 .count() ) );
0095 }
0096 return {
0097 FDuration(mean(times.data(), times.data() + times.size())),
0098 classify_outliers(times.data(), times.data() + times.size()),
0099 };
0100 }
0101
0102 template <typename Clock>
0103 Environment measure_environment() {
0104 #if defined(__clang__)
0105 # pragma clang diagnostic push
0106 # pragma clang diagnostic ignored "-Wexit-time-destructors"
0107 #endif
0108 static Catch::Detail::unique_ptr<Environment> env;
0109 #if defined(__clang__)
0110 # pragma clang diagnostic pop
0111 #endif
0112 if (env) {
0113 return *env;
0114 }
0115
0116 auto iters = Detail::warmup<Clock>();
0117 auto resolution = Detail::estimate_clock_resolution<Clock>(iters);
0118 auto cost = Detail::estimate_clock_cost<Clock>(resolution.mean);
0119
0120 env = Catch::Detail::make_unique<Environment>( Environment{resolution, cost} );
0121 return *env;
0122 }
0123 }
0124 }
0125 }
0126
0127 #endif