| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 | /* *  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) */ // Environment measurement#ifndef TWOBLUECUBES_CATCH_DETAIL_ESTIMATE_CLOCK_HPP_INCLUDED#define TWOBLUECUBES_CATCH_DETAIL_ESTIMATE_CLOCK_HPP_INCLUDED#include "../catch_clock.hpp"#include "../catch_environment.hpp"#include "catch_stats.hpp"#include "catch_measure.hpp"#include "catch_run_for_at_least.hpp"#include "../catch_clock.hpp"#include <algorithm>#include <iterator>#include <tuple>#include <vector>#include <cmath>namespace Catch {    namespace Benchmark {        namespace Detail {            template <typename Clock>            std::vector<double> resolution(int k) {                std::vector<TimePoint<Clock>> times;                times.reserve(k + 1);                std::generate_n(std::back_inserter(times), k + 1, now<Clock>{});                std::vector<double> deltas;                deltas.reserve(k);                std::transform(std::next(times.begin()), times.end(), times.begin(),                    std::back_inserter(deltas),                    [](TimePoint<Clock> a, TimePoint<Clock> b) { return static_cast<double>((a - b).count()); });                return deltas;            }            const auto warmup_iterations = 10000;            const auto warmup_time = std::chrono::milliseconds(100);            const auto minimum_ticks = 1000;            const auto warmup_seed = 10000;            const auto clock_resolution_estimation_time = std::chrono::milliseconds(500);            const auto clock_cost_estimation_time_limit = std::chrono::seconds(1);            const auto clock_cost_estimation_tick_limit = 100000;            const auto clock_cost_estimation_time = std::chrono::milliseconds(10);            const auto clock_cost_estimation_iterations = 10000;            template <typename Clock>            int warmup() {                return run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(warmup_time), warmup_seed, &resolution<Clock>)                    .iterations;            }            template <typename Clock>            EnvironmentEstimate<FloatDuration<Clock>> estimate_clock_resolution(int iterations) {                auto r = run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(clock_resolution_estimation_time), iterations, &resolution<Clock>)                    .result;                return {                    FloatDuration<Clock>(mean(r.begin(), r.end())),                    classify_outliers(r.begin(), r.end()),                };            }            template <typename Clock>            EnvironmentEstimate<FloatDuration<Clock>> estimate_clock_cost(FloatDuration<Clock> resolution) {                auto time_limit = (std::min)(                    resolution * clock_cost_estimation_tick_limit,                    FloatDuration<Clock>(clock_cost_estimation_time_limit));                auto time_clock = [](int k) {                    return Detail::measure<Clock>([k] {                        for (int i = 0; i < k; ++i) {                            volatile auto ignored = Clock::now();                            (void)ignored;                        }                    }).elapsed;                };                time_clock(1);                int iters = clock_cost_estimation_iterations;                auto&& r = run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(clock_cost_estimation_time), iters, time_clock);                std::vector<double> times;                int nsamples = static_cast<int>(std::ceil(time_limit / r.elapsed));                times.reserve(nsamples);                std::generate_n(std::back_inserter(times), nsamples, [time_clock, &r] {                    return static_cast<double>((time_clock(r.iterations) / r.iterations).count());                });                return {                    FloatDuration<Clock>(mean(times.begin(), times.end())),                    classify_outliers(times.begin(), times.end()),                };            }            template <typename Clock>            Environment<FloatDuration<Clock>> measure_environment() {                static Environment<FloatDuration<Clock>>* env = nullptr;                if (env) {                    return *env;                }                auto iters = Detail::warmup<Clock>();                auto resolution = Detail::estimate_clock_resolution<Clock>(iters);                auto cost = Detail::estimate_clock_cost<Clock>(resolution.mean);                env = new Environment<FloatDuration<Clock>>{ resolution, cost };                return *env;            }        } // namespace Detail    } // namespace Benchmark} // namespace Catch#endif // TWOBLUECUBES_CATCH_DETAIL_ESTIMATE_CLOCK_HPP_INCLUDED
 |