34 requires std::is_same_v<T, std::chrono::nanoseconds> ||
35 std::is_same_v<T, std::chrono::microseconds> ||
36 std::is_same_v<T, std::chrono::milliseconds> ||
37 std::is_same_v<T, std::chrono::seconds> ||
38 std::is_same_v<T, std::chrono::minutes> ||
39 std::is_same_v<T, std::chrono::hours>;
43concept HasSize =
requires(
const T& t) { { t.size() } -> std::convertible_to<std::size_t>; };
45template <ChronoDuration T>
48 if constexpr (std::is_same_v<T, std::chrono::nanoseconds>) {
return "ns"; }
49 else if constexpr (std::is_same_v<T, std::chrono::microseconds>) {
return "μs"; }
50 else if constexpr (std::is_same_v<T, std::chrono::milliseconds>) {
return "ms"; }
51 else if constexpr (std::is_same_v<T, std::chrono::seconds>) {
return "s"; }
52 else if constexpr (std::is_same_v<T, std::chrono::minutes>) {
return "min"; }
53 else if constexpr (std::is_same_v<T, std::chrono::hours>) {
return "h"; }
54 else {
return "units"; }
58template <ChronoDuration Unit>
66 RuntimeProfile(std::vector<Unit>&& _raw_durations, std::vector<size_t>&& _sample_sizes) noexcept
73 template <ChronoDuration OtherUnit>
86 template <ChronoDuration UnitTo>
97template <ChronoDuration Unit = std::chrono::milliseconds,
typename Func,
typename... Args>
98requires std::invocable<Func, Args...>
101 const auto start = std::chrono::high_resolution_clock::now();
103 if constexpr (std::is_void_v<std::invoke_result_t<Func, Args...>>)
105 std::invoke(std::forward<Func>(func), std::forward<Args>(args)...);
109 [[maybe_unused]]
auto result = std::invoke(std::forward<Func>(func), std::forward<Args>(args)...);
112 const auto end = std::chrono::high_resolution_clock::now();
113 return std::chrono::duration_cast<Unit>(end - start);
116template <ChronoDuration Unit = std::chrono::milliseconds,
118 std::ranges::range Container,
120requires HasSize<std::ranges::range_value_t<Container>> &&
121 std::invocable<Func, const std::ranges::range_value_t<Container>&, Args...>
122[[nodiscard]]
auto profile_runtime(Func&& func,
const Container& samples, Args&&... args)
124 if (std::ranges::empty(samples))
126 throw std::invalid_argument(
"Cannot profile runtime with empty samples container");
129 std::vector<Unit> raw_durations;
130 std::vector<size_t> sample_sizes;
131 const auto num_samples = std::ranges::size(samples);
133 raw_durations.reserve(num_samples);
134 sample_sizes.reserve(num_samples);
137 auto invoke_func = [&func, ... captured_args = std::forward<Args>(args)](
const auto& sample)
mutable {
138 std::invoke(func, sample, std::forward<Args>(captured_args)...);
141 for (
const auto& sample : samples)
145 raw_durations.emplace_back(duration);
146 sample_sizes.emplace_back(sample.size());
152template <ChronoDuration Unit>
155 if (profile.raw_durations.empty())
return Unit::zero();
157 typename Unit::rep total = 0;
158 for (
const auto& duration : profile.raw_durations) { total += duration.count(); }
159 return Unit{total / profile.raw_durations.size()};
162template <ChronoDuration Unit>
165 typename Unit::rep total = 0;
166 for (
const auto& duration : profile.raw_durations) { total += duration.count(); }
Definition runtime_analyzer.hpp:32
Definition runtime_analyzer.hpp:43
Definition runtime_analyzer.hpp:28
constexpr std::string_view get_unit_symbol() noexcept
Definition runtime_analyzer.hpp:46
auto profile_runtime(Func &&func, const Container &samples, Args &&... args)
Definition runtime_analyzer.hpp:122
auto calculate_total(const RuntimeProfile< Unit > &profile) noexcept
Definition runtime_analyzer.hpp:163
auto calculate_average(const RuntimeProfile< Unit > &profile) noexcept
Definition runtime_analyzer.hpp:153
auto measure_duration(Func &&func, Args &&... args)
Definition runtime_analyzer.hpp:99
Definition runtime_analyzer.hpp:60
std::string unit_symbol
Definition runtime_analyzer.hpp:63
RuntimeProfile(const RuntimeProfile< OtherUnit > &other)
Definition runtime_analyzer.hpp:74
RuntimeProfile< UnitTo > convert_to() const
Definition runtime_analyzer.hpp:87
std::vector< Unit > raw_durations
Definition runtime_analyzer.hpp:61
RuntimeProfile(std::vector< Unit > &&_raw_durations, std::vector< size_t > &&_sample_sizes) noexcept
Definition runtime_analyzer.hpp:66
bool empty() const noexcept
Definition runtime_analyzer.hpp:94
std::size_t size() const noexcept
Definition runtime_analyzer.hpp:93
std::vector< size_t > sample_sizes
Definition runtime_analyzer.hpp:62