Ответ 1
То, что вы описываете, называется гистограммой.
Использование хэша, если вы намереваетесь наносекундную точность, будет поглощать большую часть вашего процессора. Вероятно, вам нужен буфер для хранения данных.
Используйте std:: chrono для достижения требуемой точности синхронизации, но откровенно удары в секунду кажутся самой высокой степенью детализации, и если вы смотрите на общую общую картину, похоже, что это не будет иметь особого значения точность.
Это частичный, вводный пример того, как вы можете это сделать:
#include <array>
#include <algorithm>
template<size_t RingSize>
class Histogram
{
std::array<size_t, RingSize> m_ringBuffer;
size_t m_total;
size_t m_position;
public:
Histogram() : m_total(0)
{
std::fill_n(m_ringBuffer.begin(), RingSize, 0);
}
void addHit()
{
++m_ringBuffer[m_position];
++m_total;
}
void incrementPosition()
{
if (++m_position >= RingSize)
m_position = 0;
m_total -= m_ringBuffer[m_position];
m_ringBuffer[m_position] = 0;
}
double runningAverage() const
{
return (double)m_total / (double)RingSize;
}
size_t runningTotal() const { return m_total; }
};
Histogram<60> secondsHisto;
Histogram<60> minutesHisto;
Histogram<24> hoursHisto;
Histogram<7> weeksHisto;
Это наивная реализация, которая предполагает, что вы будете называть ее каждую секунду и увеличивать позицию, и будет транспонировать runningTotal с одной гистограммы на следующую каждый RingSize (поэтому каждые 60 секунд добавьте secondsHisto.runningTotal в minutesHisto).
Надеюсь, это будет полезное вводное место для начала.
Если вы хотите отслеживать более длинную гистограмму обращений в секунду, вы можете сделать это с помощью этой модели, увеличив размер кольца, добавив вторую общую сумму для отслеживания последних записей кольцевого буфера N, чтобы m_subTotal = sum (m_ringBuffer [m_position - N.. m_position]), аналогично тому, как работает m_total.
size_t m_10sTotal;
...
void addHit()
{
++m_ringBuffer[m_position];
++m_total;
++m_10sTotal;
}
void incrementPosition()
{
// subtract data from >10 sample intervals ago.
m_10sTotal -= m_ringBuffer[(m_position + RingBufferSize - 10) % RingBufferSize];
// for the naive total, do the subtraction after we
// advance position, since it will coincide with the
// location of the value RingBufferSize ago.
if (++m_position >= RingBufferSize)
m_position = 0;
m_total -= m_ringBuffer[m_position];
}
Вам не нужно составлять гистограммы этих размеров, это просто наивная модель выскабливания. Существуют различные альтернативы, такие как увеличение каждой гистограммы одновременно:
secondsHisto.addHit();
minutesHisto.addHit();
hoursHisto.addHit();
weeksHisto.addHit();
Каждый катится независимо, поэтому все имеют текущие значения. Размер каждого гистона, если вы хотите, чтобы данные в этой гранулярности возвращались назад.