Move Average into average.hh
Moved the class to a more appropriate place.
This commit is contained in:
@ -13,6 +13,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <maxbase/ccdefs.hh>
|
#include <maxbase/ccdefs.hh>
|
||||||
|
#include <maxbase/atomic.hh>
|
||||||
|
#include <maxbase/assert.h>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -32,28 +34,28 @@ public:
|
|||||||
* @param ave The average value
|
* @param ave The average value
|
||||||
* @param num_samples How many samples were taken to construct it
|
* @param num_samples How many samples were taken to construct it
|
||||||
*/
|
*/
|
||||||
void add(double ave, int num_samples = 1);
|
void add(double ave, int num_samples = 1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the average value
|
* Get the average value
|
||||||
*
|
*
|
||||||
* @return The average value
|
* @return The average value
|
||||||
*/
|
*/
|
||||||
double average() const;
|
double average() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get number of samples
|
* Get number of samples
|
||||||
*
|
*
|
||||||
* @return Number of collected samples
|
* @return Number of collected samples
|
||||||
*/
|
*/
|
||||||
int num_samples() const;
|
int num_samples() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset the average value
|
* Reset the average value
|
||||||
*
|
*
|
||||||
* Sets the average to 0.0 and number of samples to 0.
|
* Sets the average to 0.0 and number of samples to 0.
|
||||||
*/
|
*/
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
CumulativeAverage& operator+=(const CumulativeAverage& rhs);
|
CumulativeAverage& operator+=(const CumulativeAverage& rhs);
|
||||||
private:
|
private:
|
||||||
@ -99,7 +101,7 @@ public:
|
|||||||
* @param ave Value to add
|
* @param ave Value to add
|
||||||
* @param num_samples Number of samples the value consists of
|
* @param num_samples Number of samples the value consists of
|
||||||
*/
|
*/
|
||||||
void add(double ave, int num_samples = 1);
|
void add(double ave, int num_samples = 1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a CumulativeAverage
|
* Add a CumulativeAverage
|
||||||
@ -108,7 +110,7 @@ public:
|
|||||||
*
|
*
|
||||||
* @param ca CumulativeAverage to add
|
* @param ca CumulativeAverage to add
|
||||||
*/
|
*/
|
||||||
void add(const CumulativeAverage& ca);
|
void add(const CumulativeAverage& ca);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current average value
|
* Get the current average value
|
||||||
@ -122,28 +124,28 @@ public:
|
|||||||
*
|
*
|
||||||
* @return The number of samples
|
* @return The number of samples
|
||||||
*/
|
*/
|
||||||
int num_samples() const;
|
int num_samples() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set maximum sample size
|
* Set maximum sample size
|
||||||
*
|
*
|
||||||
* @param sample_max The new sample max size
|
* @param sample_max The new sample max size
|
||||||
*/
|
*/
|
||||||
void set_sample_max(int sample_max);
|
void set_sample_max(int sample_max);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get maximum sample size
|
* Get maximum sample size
|
||||||
*
|
*
|
||||||
* @return The maximum sample size
|
* @return The maximum sample size
|
||||||
*/
|
*/
|
||||||
int sample_max() const;
|
int sample_max() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset the average
|
* Reset the average
|
||||||
*
|
*
|
||||||
* Sets average value to 0.0 and number of samples to 0.
|
* Sets average value to 0.0 and number of samples to 0.
|
||||||
*/
|
*/
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const double m_min_alpha;
|
const double m_min_alpha;
|
||||||
@ -152,4 +154,241 @@ private:
|
|||||||
int m_num_samples = 0;
|
int m_num_samples = 0;
|
||||||
double m_ave = 0;
|
double m_ave = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Average is a base class for classes intended to be used for calculating
|
||||||
|
* averages. An Average may have a dependant Average whose value depends
|
||||||
|
* upon the value of the first. At certain moments, an Average may trigger
|
||||||
|
* its dependant Average to update itself.
|
||||||
|
*/
|
||||||
|
class Average
|
||||||
|
{
|
||||||
|
Average(const Average&) = delete;
|
||||||
|
Average& operator=(const Average&) = delete;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param pDependant An optional dependant average.
|
||||||
|
*/
|
||||||
|
Average(Average* pDependant = NULL)
|
||||||
|
: m_pDependant(pDependant)
|
||||||
|
, m_value(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a value to the Average. The exact meaning depends upon the
|
||||||
|
* concrete Average class.
|
||||||
|
*
|
||||||
|
* If the addition of the value in some sense represents a full cycle
|
||||||
|
* in the average calculation, then the instance will call add_value()
|
||||||
|
* on its dependant, otherwise it will call update_value(). In both cases
|
||||||
|
* with its own value as argument.
|
||||||
|
*
|
||||||
|
* @param value The value to be added.
|
||||||
|
*
|
||||||
|
* @return True if the addition of the value caused a full cycle
|
||||||
|
* in the average calculation, false otherwise.
|
||||||
|
*/
|
||||||
|
virtual bool add_value(uint8_t value) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the value of the Average. The exact meaning depends upon the
|
||||||
|
* concrete Average class. Will also call update_value() of its dependant
|
||||||
|
* with its own value as argument.
|
||||||
|
*
|
||||||
|
* @param value The value to be updated.
|
||||||
|
*/
|
||||||
|
virtual void update_value(uint8_t value) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the average value.
|
||||||
|
*
|
||||||
|
* @return The value represented by the Average.
|
||||||
|
*/
|
||||||
|
uint8_t value() const
|
||||||
|
{
|
||||||
|
return mxb::atomic::load(&m_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Average* m_pDependant; /*< The optional dependant Average. */
|
||||||
|
uint32_t m_value; /*< The current average value. */
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void set_value(uint32_t value)
|
||||||
|
{
|
||||||
|
mxb::atomic::store(&m_value, value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An Average consisting of a single value.
|
||||||
|
*/
|
||||||
|
class Average1 : public Average
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Average1(Average* pDependant = NULL)
|
||||||
|
: Average(pDependant)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool add_value(uint8_t value)
|
||||||
|
{
|
||||||
|
set_value(value);
|
||||||
|
|
||||||
|
// Every addition of a value represents a full cycle.
|
||||||
|
if (m_pDependant)
|
||||||
|
{
|
||||||
|
m_pDependant->add_value(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_value(uint8_t value)
|
||||||
|
{
|
||||||
|
set_value(value);
|
||||||
|
|
||||||
|
if (m_pDependant)
|
||||||
|
{
|
||||||
|
m_pDependant->update_value(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An Average calculated from N values.
|
||||||
|
*/
|
||||||
|
template<size_t N>
|
||||||
|
class AverageN : public Average
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AverageN(Average* pDependant = NULL)
|
||||||
|
: Average(pDependant)
|
||||||
|
, m_end(m_begin + N)
|
||||||
|
, m_i(m_begin)
|
||||||
|
, m_sum(0)
|
||||||
|
, m_nValues(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool add_value(uint8_t value)
|
||||||
|
{
|
||||||
|
if (m_nValues == N)
|
||||||
|
{
|
||||||
|
// If as many values that fit has been added, then remove the
|
||||||
|
// least recent value from the sum.
|
||||||
|
m_sum -= *m_i;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Otherwise make a note that a new value is added.
|
||||||
|
++m_nValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
*m_i = value;
|
||||||
|
m_sum += *m_i; // Update the sum of all values.
|
||||||
|
|
||||||
|
m_i = next(m_i);
|
||||||
|
|
||||||
|
uint32_t average = m_sum / m_nValues;
|
||||||
|
|
||||||
|
set_value(average);
|
||||||
|
|
||||||
|
if (m_pDependant)
|
||||||
|
{
|
||||||
|
if (m_i == m_begin)
|
||||||
|
{
|
||||||
|
// If we have looped around we have performed a full cycle and will
|
||||||
|
// add a new value to the dependant average.
|
||||||
|
m_pDependant->add_value(average);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Otherwise we just update the most recent value.
|
||||||
|
m_pDependant->update_value(average);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_i == m_begin;
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_value(uint8_t value)
|
||||||
|
{
|
||||||
|
if (m_nValues == 0)
|
||||||
|
{
|
||||||
|
// If no values have been added yet, there's nothing to update but we
|
||||||
|
// need to add the value.
|
||||||
|
add_value(value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Otherwise we update the most recent value.
|
||||||
|
uint8_t* p = prev(m_i);
|
||||||
|
|
||||||
|
m_sum -= *p;
|
||||||
|
*p = value;
|
||||||
|
m_sum += *p;
|
||||||
|
|
||||||
|
uint32_t average = m_sum / m_nValues;
|
||||||
|
|
||||||
|
set_value(average);
|
||||||
|
|
||||||
|
if (m_pDependant)
|
||||||
|
{
|
||||||
|
m_pDependant->update_value(average);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8_t* prev(uint8_t* p)
|
||||||
|
{
|
||||||
|
mxb_assert(p >= m_begin);
|
||||||
|
mxb_assert(p < m_end);
|
||||||
|
|
||||||
|
if (p > m_begin)
|
||||||
|
{
|
||||||
|
--p;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mxb_assert(p == m_begin);
|
||||||
|
p = m_end - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mxb_assert(p >= m_begin);
|
||||||
|
mxb_assert(p < m_end);
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t* next(uint8_t* p)
|
||||||
|
{
|
||||||
|
mxb_assert(p >= m_begin);
|
||||||
|
mxb_assert(p < m_end);
|
||||||
|
|
||||||
|
++p;
|
||||||
|
|
||||||
|
if (p == m_end)
|
||||||
|
{
|
||||||
|
p = m_begin;
|
||||||
|
}
|
||||||
|
|
||||||
|
mxb_assert(p >= m_begin);
|
||||||
|
mxb_assert(p < m_end);
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8_t m_begin[N]; /*< Buffer containing values from which the average is calculated. */
|
||||||
|
uint8_t* m_end; /*< Points to one past the end of the buffer. */
|
||||||
|
uint8_t* m_i; /*< Current position in the buffer. */
|
||||||
|
uint32_t m_sum; /*< Sum of all values in the buffer. */
|
||||||
|
uint32_t m_nValues; /*< How many values the buffer contains. */
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include <maxbase/assert.h>
|
#include <maxbase/assert.h>
|
||||||
#include <maxbase/atomic.h>
|
#include <maxbase/atomic.h>
|
||||||
|
#include <maxbase/average.hh>
|
||||||
#include <maxbase/messagequeue.hh>
|
#include <maxbase/messagequeue.hh>
|
||||||
#include <maxbase/semaphore.hh>
|
#include <maxbase/semaphore.hh>
|
||||||
#include <maxbase/worker.h>
|
#include <maxbase/worker.h>
|
||||||
@ -175,244 +176,6 @@ public:
|
|||||||
static uint64_t get_time();
|
static uint64_t get_time();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
|
||||||
* Average is a base class for classes intended to be used for calculating
|
|
||||||
* averages. An Average may have a dependant Average whose value depends
|
|
||||||
* upon the value of the first. At certain moments, an Average may trigger
|
|
||||||
* its dependant Average to update itself.
|
|
||||||
*/
|
|
||||||
class Average
|
|
||||||
{
|
|
||||||
Average(const Average&) = delete;
|
|
||||||
Average& operator=(const Average&) = delete;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*
|
|
||||||
* @param pDependant An optional dependant average.
|
|
||||||
*/
|
|
||||||
Average(Average* pDependant = NULL)
|
|
||||||
: m_pDependant(pDependant)
|
|
||||||
, m_value(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~Average();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a value to the Average. The exact meaning depends upon the
|
|
||||||
* concrete Average class.
|
|
||||||
*
|
|
||||||
* If the addition of the value in some sense represents a full cycle
|
|
||||||
* in the average calculation, then the instance will call add_value()
|
|
||||||
* on its dependant, otherwise it will call update_value(). In both cases
|
|
||||||
* with its own value as argument.
|
|
||||||
*
|
|
||||||
* @param value The value to be added.
|
|
||||||
*
|
|
||||||
* @return True if the addition of the value caused a full cycle
|
|
||||||
* in the average calculation, false otherwise.
|
|
||||||
*/
|
|
||||||
virtual bool add_value(uint8_t value) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the value of the Average. The exact meaning depends upon the
|
|
||||||
* concrete Average class. Will also call update_value() of its dependant
|
|
||||||
* with its own value as argument.
|
|
||||||
*
|
|
||||||
* @param value The value to be updated.
|
|
||||||
*/
|
|
||||||
virtual void update_value(uint8_t value) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the average value.
|
|
||||||
*
|
|
||||||
* @return The value represented by the Average.
|
|
||||||
*/
|
|
||||||
uint8_t value() const
|
|
||||||
{
|
|
||||||
return atomic_load_uint32(&m_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Average* m_pDependant; /*< The optional dependant Average. */
|
|
||||||
uint32_t m_value; /*< The current average value. */
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void set_value(uint32_t value)
|
|
||||||
{
|
|
||||||
atomic_store_uint32(&m_value, value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An Average consisting of a single value.
|
|
||||||
*/
|
|
||||||
class Average1 : public Average
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Average1(Average* pDependant = NULL)
|
|
||||||
: Average(pDependant)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool add_value(uint8_t value)
|
|
||||||
{
|
|
||||||
set_value(value);
|
|
||||||
|
|
||||||
// Every addition of a value represents a full cycle.
|
|
||||||
if (m_pDependant)
|
|
||||||
{
|
|
||||||
m_pDependant->add_value(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void update_value(uint8_t value)
|
|
||||||
{
|
|
||||||
set_value(value);
|
|
||||||
|
|
||||||
if (m_pDependant)
|
|
||||||
{
|
|
||||||
m_pDependant->update_value(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An Average calculated from N values.
|
|
||||||
*/
|
|
||||||
template<size_t N>
|
|
||||||
class AverageN : public Average
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AverageN(Average* pDependant = NULL)
|
|
||||||
: Average(pDependant)
|
|
||||||
, m_end(m_begin + N)
|
|
||||||
, m_i(m_begin)
|
|
||||||
, m_sum(0)
|
|
||||||
, m_nValues(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool add_value(uint8_t value)
|
|
||||||
{
|
|
||||||
if (m_nValues == N)
|
|
||||||
{
|
|
||||||
// If as many values that fit has been added, then remove the
|
|
||||||
// least recent value from the sum.
|
|
||||||
m_sum -= *m_i;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Otherwise make a note that a new value is added.
|
|
||||||
++m_nValues;
|
|
||||||
}
|
|
||||||
|
|
||||||
*m_i = value;
|
|
||||||
m_sum += *m_i; // Update the sum of all values.
|
|
||||||
|
|
||||||
m_i = next(m_i);
|
|
||||||
|
|
||||||
uint32_t average = m_sum / m_nValues;
|
|
||||||
|
|
||||||
set_value(average);
|
|
||||||
|
|
||||||
if (m_pDependant)
|
|
||||||
{
|
|
||||||
if (m_i == m_begin)
|
|
||||||
{
|
|
||||||
// If we have looped around we have performed a full cycle and will
|
|
||||||
// add a new value to the dependant average.
|
|
||||||
m_pDependant->add_value(average);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Otherwise we just update the most recent value.
|
|
||||||
m_pDependant->update_value(average);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_i == m_begin;
|
|
||||||
}
|
|
||||||
|
|
||||||
void update_value(uint8_t value)
|
|
||||||
{
|
|
||||||
if (m_nValues == 0)
|
|
||||||
{
|
|
||||||
// If no values have been added yet, there's nothing to update but we
|
|
||||||
// need to add the value.
|
|
||||||
add_value(value);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Otherwise we update the most recent value.
|
|
||||||
uint8_t* p = prev(m_i);
|
|
||||||
|
|
||||||
m_sum -= *p;
|
|
||||||
*p = value;
|
|
||||||
m_sum += *p;
|
|
||||||
|
|
||||||
uint32_t average = m_sum / m_nValues;
|
|
||||||
|
|
||||||
set_value(average);
|
|
||||||
|
|
||||||
if (m_pDependant)
|
|
||||||
{
|
|
||||||
m_pDependant->update_value(average);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
uint8_t* prev(uint8_t* p)
|
|
||||||
{
|
|
||||||
mxb_assert(p >= m_begin);
|
|
||||||
mxb_assert(p < m_end);
|
|
||||||
|
|
||||||
if (p > m_begin)
|
|
||||||
{
|
|
||||||
--p;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mxb_assert(p == m_begin);
|
|
||||||
p = m_end - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
mxb_assert(p >= m_begin);
|
|
||||||
mxb_assert(p < m_end);
|
|
||||||
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t* next(uint8_t* p)
|
|
||||||
{
|
|
||||||
mxb_assert(p >= m_begin);
|
|
||||||
mxb_assert(p < m_end);
|
|
||||||
|
|
||||||
++p;
|
|
||||||
|
|
||||||
if (p == m_end)
|
|
||||||
{
|
|
||||||
p = m_begin;
|
|
||||||
}
|
|
||||||
|
|
||||||
mxb_assert(p >= m_begin);
|
|
||||||
mxb_assert(p < m_end);
|
|
||||||
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
uint8_t m_begin[N]; /*< Buffer containing values from which the average is calculated. */
|
|
||||||
uint8_t* m_end; /*< Points to one past the end of the buffer. */
|
|
||||||
uint8_t* m_i; /*< Current position in the buffer. */
|
|
||||||
uint32_t m_sum; /*< Sum of all values in the buffer. */
|
|
||||||
uint32_t m_nValues; /*< How many values the buffer contains. */
|
|
||||||
};
|
|
||||||
|
|
||||||
uint64_t m_start_time; /*< When was the current 1-second period started. */
|
uint64_t m_start_time; /*< When was the current 1-second period started. */
|
||||||
uint64_t m_wait_start; /*< The time when the worker entered epoll_wait(). */
|
uint64_t m_wait_start; /*< The time when the worker entered epoll_wait(). */
|
||||||
|
@ -103,10 +103,6 @@ void WorkerLoad::about_to_work(uint64_t now)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WorkerLoad::Average::~Average()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
// static
|
||||||
uint64_t WorkerLoad::get_time()
|
uint64_t WorkerLoad::get_time()
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user