@ -1,66 +0,0 @@ | |||
/* | |||
* Copyright (C) 2023 Christopher J. Howard | |||
* | |||
* This file is part of Antkeeper source code. | |||
* | |||
* Antkeeper source code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
* the Free Software Foundation, either version 3 of the License, or | |||
* (at your option) any later version. | |||
* | |||
* Antkeeper source code is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU General Public License | |||
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#include "performance-sampler.hpp" | |||
#include <algorithm> | |||
#include <numeric> | |||
namespace debug { | |||
performance_sampler::performance_sampler(): | |||
sample_size(1), | |||
sample_index(0) | |||
{} | |||
void performance_sampler::sample(double duration) | |||
{ | |||
if (samples.size() < sample_size) | |||
{ | |||
samples.push_back(duration); | |||
} | |||
else | |||
{ | |||
samples[sample_index] = duration; | |||
sample_index = (sample_index + 1) % samples.size(); | |||
} | |||
} | |||
void performance_sampler::reset() | |||
{ | |||
samples.clear(); | |||
sample_index = 0; | |||
} | |||
void performance_sampler::set_sample_size(std::size_t size) | |||
{ | |||
sample_size = size; | |||
if (samples.size() > size) | |||
{ | |||
samples.resize(size); | |||
sample_index = 0; | |||
} | |||
} | |||
double performance_sampler::mean_frame_duration() const | |||
{ | |||
return std::accumulate(samples.begin(), samples.end(), 0.0) / static_cast<double>(samples.size()); | |||
} | |||
} // namespace debug | |||
@ -1,69 +0,0 @@ | |||
/* | |||
* Copyright (C) 2023 Christopher J. Howard | |||
* | |||
* This file is part of Antkeeper source code. | |||
* | |||
* Antkeeper source code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
* the Free Software Foundation, either version 3 of the License, or | |||
* (at your option) any later version. | |||
* | |||
* Antkeeper source code is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU General Public License | |||
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef ANTKEEPER_DEBUG_PERFORMANCE_SAMPLER_HPP | |||
#define ANTKEEPER_DEBUG_PERFORMANCE_SAMPLER_HPP | |||
#include <cstddef> | |||
#include <vector> | |||
namespace debug { | |||
/** | |||
* Measures a rolling mean frame duration. | |||
*/ | |||
class performance_sampler | |||
{ | |||
public: | |||
/// Creates a performance sampler. | |||
performance_sampler(); | |||
/** | |||
* Adds a frame duration to the sample. | |||
* | |||
* @param duration Duration of the frame. | |||
*/ | |||
void sample(double duration); | |||
/** | |||
* Resets the sampling process. | |||
*/ | |||
void reset(); | |||
/** | |||
* Sets the number of frames in a sample. | |||
* | |||
* @param size Number of frames in a sample. | |||
*/ | |||
void set_sample_size(std::size_t size); | |||
/** | |||
* Returns the mean frame duration. | |||
*/ | |||
[[nodiscard]] double mean_frame_duration() const; | |||
private: | |||
std::vector<double> samples; | |||
std::size_t sample_size; | |||
std::size_t sample_index; | |||
}; | |||
} // namespace debug | |||
#endif // ANTKEEPER_DEBUG_PERFORMANCE_SAMPLER_HPP |
@ -0,0 +1,138 @@ | |||
/* | |||
* Copyright (C) 2023 Christopher J. Howard | |||
* | |||
* This file is part of Antkeeper source code. | |||
* | |||
* Antkeeper source code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
* the Free Software Foundation, either version 3 of the License, or | |||
* (at your option) any later version. | |||
* | |||
* Antkeeper source code is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU General Public License | |||
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef ANTKEEPER_MATH_MOVING_AVERAGE_HPP | |||
#define ANTKEEPER_MATH_MOVING_AVERAGE_HPP | |||
#include <algorithm> | |||
#include <cstdint> | |||
#include <vector> | |||
namespace math { | |||
/** | |||
* Calculates a moving average. | |||
* | |||
* @tparam T Value type. | |||
* @tparam N Sample capacity. | |||
*/ | |||
template <class T, std::size_t N> | |||
class moving_average | |||
{ | |||
public: | |||
/// Type of value to average. | |||
typedef T value_type; | |||
/// Constructs a moving average | |||
moving_average(): | |||
m_sample_index{0}, | |||
m_sum{0}, | |||
m_average{0} | |||
{} | |||
/** | |||
* Adds a sample to the moving average. If the moving average has reached its sample capacity, the oldest sample will be discarded. | |||
* | |||
* @param value Sample value. | |||
* | |||
* @return Current average value. | |||
*/ | |||
value_type operator()(value_type value) noexcept | |||
{ | |||
m_sum += value; | |||
if (m_sample_index < N) | |||
{ | |||
m_samples[m_sample_index] = value; | |||
++m_sample_index; | |||
m_average = m_sum / static_cast<value_type>(m_sample_index); | |||
} | |||
else | |||
{ | |||
value_type& sample = m_samples[m_sample_index % N]; | |||
m_sum -= sample; | |||
sample = value; | |||
++m_sample_index; | |||
m_average = m_sum / static_cast<value_type>(N); | |||
} | |||
return m_average; | |||
} | |||
/** | |||
* Resets the moving average. | |||
*/ | |||
void reset() noexcept | |||
{ | |||
m_sample_index = 0; | |||
m_sum = value_type{0}; | |||
m_average = value_type{0}; | |||
} | |||
/// Returns a pointer to the sample data. | |||
[[nodiscard]] inline constexpr value_type* data() const noexcept | |||
{ | |||
return m_samples.data(); | |||
} | |||
/// Returns the current moving average value. | |||
[[nodiscard]] inline value_type average() const noexcept | |||
{ | |||
return m_average; | |||
} | |||
///Returns the sum of all current samples. | |||
[[nodiscard]] inline value_type sum() const noexcept | |||
{ | |||
return m_sum; | |||
} | |||
/// Returns the current number of samples. | |||
[[nodiscard]] inline std::size_t size() const noexcept | |||
{ | |||
return std::min<std::size_t>(m_sample_index, N); | |||
} | |||
/// Returns the maximum number of samples. | |||
[[nodiscard]] inline constexpr std::size_t capacity() const noexcept | |||
{ | |||
return N; | |||
} | |||
/// Return `true` if there are currently no samples in the average, `false` otherwise. | |||
[[nodiscard]] inline constexpr bool empty() const noexcept | |||
{ | |||
return !m_sample_index; | |||
} | |||
/// Return `true` if the number of samples in the average has reached its capacity, `false` otherwise. | |||
[[nodiscard]] inline constexpr bool full() const noexcept | |||
{ | |||
return m_sample_index >= N; | |||
} | |||
private: | |||
std::size_t m_sample_index; | |||
value_type m_samples[N]; | |||
value_type m_sum; | |||
value_type m_average; | |||
}; | |||
} // namespace math | |||
#endif // ANTKEEPER_MATH_MOVING_AVERAGE_HPP |