#ifndef CLICK_EWMA_HH #define CLICK_EWMA_HH #include #include CLICK_DECLS /** @file * @brief Click's classes for supporting exponentially weighted moving * averages. */ /** @class DirectEWMAX include/click/ewma.hh * @brief An exponentially weighted moving average. * * The DirectEWMAX template class represents a simple exponentially weighted * moving average. The average starts out with value 0. The update() * function adds a new observation to the average. * * The template parameter P defines three EWMA parameters: value type, * stability shift, and scale factor. * * The value type is simply the unsigned integral type used to store the * average. It is also the type of each observation. unsigned * and uint64_t are examples. * * The stability shift specifies alpha, the stability parameter. Concretely, * alpha = 1. / (2 ** stability_shift). Thus, a stability shift of 4 * corresponds to an alpha of 1/16. * * The scaling factor specifies how many bits of fraction are kept per * observation. Fraction bits are necessary to account for small differences * between observations. For example, consider a EWMA with value 0, alpha * 1/16, and 0 bits of fraction. Assume the EWMA begins to observe a stream * of observations equal to 1. Despite these observations, the EWMA's value * will never change from 0, since the 1/16 alpha factor rounds the new * observations down to 0. At least 4 bits of fraction are required to * account for this difference. There is a tradeoff: the more bits of * fraction, the more precise the EWMA, but the less bits available to * account for large values. * * These EWMA parameters are defined by five of P's members, two typedefs and * three possibly static member functions. * *
*
P::value_type
*
The EWMA's value type. Example: unsigned.
* *
P::signed_value_type
*
The signed version of P::value_type. Used internally. * Example: int.
* *
unsigned P::stability_shift()
*
This function should return this EWMA's stability shift * (see above).
* *
unsigned P::scale()
*
This function should return this EWMA's scaling factor * (see above).
* *
unsigned P::compensation()
*
This function should return this EWMA's stability compensation, * which normally equals 1 @<@< (stability_shift - 1).
*
* * Since DirectEWMAX inherits from an object of type P, these members are * also directly available to callers. * * The FixedEWMAXParameters and StabilityEWMAXParameters types are good * template arguments for DirectEWMAX. * * @sa RateEWMAX */ template class DirectEWMAX : public P { public: typedef typename P::value_type value_type; /** @brief Construct a EWMA with initial average 0. */ DirectEWMAX() : _avg(0) { } /** @brief Construct a EWMA with initial scaled average @a scaled_value. */ DirectEWMAX(value_type scaled_value) : _avg(scaled_value) { } /** @brief Return the current scaled moving average. * @note The returned value has scale() bits of fraction. */ value_type scaled_average() const { return _avg; } /** @brief Return the current moving average, rounded up. * @note The returned value is unscaled (has zero bits of fraction). */ value_type unscaled_average() const { return (_avg + (P::scaled_one() >> 1)) >> P::scale(); } /** @brief Reset the EWMA to value 0. */ void clear() { _avg = 0; } /** @brief Assign the EWMA to scaled average @a scaled_value. */ inline void assign(value_type scaled_value) { _avg = scaled_value; } /** @brief Update the moving average with a new observation. * @param x the observation (unscaled) */ inline void update(value_type x); /** @brief Update the moving average with @a n identical observations. * @param x the observation (unscaled) * @param n number of observations * @note This may be faster than calling update(@a x) @a n * times. */ void update_n(value_type x, unsigned n); /** @brief Unparse the current average into a String. * @note The returned value is unscaled, but may contain a fractional * part. */ String unparse() const; /** @brief Update the moving average with a new observation (deprecated). * @param x the observation (unscaled) * @deprecated Use update() instead. */ inline void update_with(value_type x) CLICK_DEPRECATED; private: value_type _avg; }; template inline void DirectEWMAX

::update(value_type x) { value_type x_scaled = (x << P::scale()) + P::compensation(); unsigned stability = P::stability_shift(); #if HAVE_ARITHMETIC_RIGHT_SHIFT _avg += static_cast(x_scaled - _avg) >> stability; #else if (x_scaled < _avg) _avg -= (_avg - x_scaled) >> stability; else _avg += (x_scaled - _avg) >> stability; #endif } template void DirectEWMAX

::update_n(value_type x, unsigned n) { // XXX use table lookup value_type x_scaled = x << P::scale(); if (n >= 100) _avg = x_scaled; else { x_scaled += P::compensation(); unsigned stability = P::stability_shift(); #if HAVE_ARITHMETIC_RIGHT_SHIFT for (; n > 0; n--) _avg += static_cast(x_scaled - _avg) >> stability; #else if (x_scaled < _avg) for (; n > 0; n--) _avg -= (_avg - x_scaled) >> stability; else for (; n > 0; n--) _avg += (x_scaled - _avg) >> stability; #endif } } template inline String DirectEWMAX

::unparse() const { return cp_unparse_real2(scaled_average(), P::scale()); } template inline void DirectEWMAX

::update_with(value_type x) { update(x); } /** @class FixedEWMAXParameters include/click/ewma.hh * @brief Parameters for a EWMA with constant scaling factor and stability * shift. * * The FixedEWMAXParameters template class is used as a template argument to * DirectEWMAX. It defines a EWMA with fixed constant scaling factor and * stability shift. FixedEWMAXParameters's first template argument is the * EWMA's stability shift, its second template argument is the EWMA's scaling * factor, its third template argument is the EWMA's value type, and the * fourth template argument is the EWMA's signed value type. * * Example 1: DirectEWMAX@ * @> defines a EWMA with alpha 1/16 (stability shift 4), scaling * factor 10, and value type unsigned. (These are the default parameters * available in the DirectEWMA typedef.) * * Example 2: DirectEWMAX@ @> defines a EWMA with alpha 1/8 (stability shift 3), * scaling factor 10, and value type uint64_t. */ template class FixedEWMAXParameters { public: typedef T value_type; typedef U signed_value_type; /** @brief Return this EWMA's stability shift. * @return the 1st template parameter */ static unsigned stability_shift() { return STABILITY; } /** @brief Return this EWMA's scaling factor (bits of fraction). * @return the 2nd template parameter */ static unsigned scale() { static_assert(SCALE < sizeof(T) * 8, "SCALE too big for EWMA type."); return SCALE; } /** @brief Return this EWMA's scaled value for one. */ static value_type scaled_one() { return (value_type) 1 << SCALE; } /** @brief Return this EWMA's compensation. * @return 1 << (stability_shift() - 1) */ static unsigned compensation() { return 1 << (STABILITY - 1); } }; /** @brief A DirectEWMAX with stability shift 4 (alpha 1/16), scaling factor * 10 (10 bits of fraction), and underlying type unsigned. */ typedef DirectEWMAX > DirectEWMA; /** @brief A DirectEWMAX with stability shift 3 (alpha 1/8), scaling factor * 10 (10 bits of fraction), and underlying type unsigned. */ typedef DirectEWMAX > FastDirectEWMA; /** @class StabilityEWMAXParameters include/click/ewma.hh * @brief Parameters for a EWMA with constant scaling factor * and user-settable alpha. * * The StabilityEWMAXParameters template class is used as a template argument * to DirectEWMAX. It defines a EWMA with fixed constant scaling factor. * StabilityEWMAXParameters's first template argument is the EWMA's scaling * factor, its second template argument is the EWMA's value type, and the * third template argument is the EWMA's signed value type. * * Example: DirectEWMAX@ * @> defines a EWMA with user-settable alpha (stability shift) * initially equal to 1/16, scaling factor 10, and value type unsigned. * * A DirectEWMAX@ @> object has * stability_shift() and set_stability_shift() methods. */ template class StabilityEWMAXParameters { public: typedef T value_type; typedef U signed_value_type; /** @brief Construct a StabilityEWMAXParameters with initial alpha 1/16. */ StabilityEWMAXParameters() : _stability(4) { } /** @brief Return the current stability shift. * * The current alpha equals 1. / (2 ** stability_shift()). */ unsigned stability_shift() const { return _stability; } /** @brief Set the current stability shift. * @param stability_shift new value */ void set_stability_shift(unsigned stability_shift) { _stability = stability_shift; } /** @brief Return this EWMA's scaling factor (bits of fraction). * @return the 1st template parameter */ static unsigned scale() { return SCALE; } /** @brief Return this EWMA's scaled value for one. */ static value_type scaled_one() { return (value_type) 1 << SCALE; } /** @brief Return this EWMA's compensation. * @return 1 << (stability_shift() - 1) */ unsigned compensation() const { return 1 << (stability_shift() - 1); } private: unsigned _stability; }; /** @class RateEWMAX include/click/ewma.hh * @brief An exponentially weighted moving average used to measure a rate. * * The RateEWMAX template class represents an exponentially weighted moving * average that measures a rate: a count of events per unit time. * The average starts out with value 0. * * RateEWMAX adds to DirectEWMAX a concept of epochs, which are periods of * time. A RateEWMAX object collects samples over the current epoch. When * the epoch closes, the collected sample count is used to update the moving * average. Thus, the moving average is measured in samples per epoch. The * rate() and unparse_rate() member functions return the rate in samples per * second, rather than per epoch. These functions use the epoch * frequency to translate between epochs and seconds. * * Note that it often makes sense to call update() before calling * scaled_average(), rate(), or unparse_rate(), in case an epoch or two has * passed and the average should take account of passing time. * * The template parameter P defines the EWMA parameters required by * DirectEWMAX, and three others: a rate count, an epoch measurement, and an * epoch frequency. * * The rate count is the number of rates measured per object. Usually it is * 1. * * The epoch measurement is a function that returns the current epoch as an * unsigned number. Epochs should increase monotonically. * * The epoch frequency is the number of epochs per second, and is only used * by rate() and unparse_rate(). * * These are defined by: * *

*
P::rate_count
*
The rate count, as a static constant (for example, defined by an * enum).
* *
unsigned P::epoch()
*
This function returns the current epoch number.
* *
unsigned P::epoch_frequency()
*
This function returns the number of epochs per second.
*
* * Since RateEWMAX inherits from an object of type P, these members are * also directly available to callers. * * The RateEWMAXParameters type is a good template argument for RateEWMAX. * * @sa DirectEWMAX */ template class RateEWMAX : public P { public: typedef typename P::value_type value_type; typedef typename P::signed_value_type signed_value_type; /** @brief Create a rate EWMA with initial value(s) 0. */ RateEWMAX() { _current_epoch = P::epoch(); for (unsigned i = 0; i < P::rate_count; i++) _current[i] = 0; } /** @brief Return the current scaled moving average. * @param ratenum rate index (0 <= ratenum < rate_count) * @note The returned value has scale() bits of fraction. * @note scaled_average() does not check the current epoch. * If an epoch might have passed since the last update(), you * should call update(0, @a ratenum) before calling this * function. */ signed_value_type scaled_average(unsigned ratenum = 0) const { // note: return type must be signed! return _avg[ratenum].scaled_average(); } /** @brief Returns one of the average's scaling factors (bits of * fraction). */ unsigned scale(unsigned ratenum = 0) const { return _avg[ratenum].scale(); } /** @brief Return the current rate in samples per second. * @param ratenum rate index (0 <= ratenum < rate_count) * @note The returned value is unscaled. * @note rate() does not check the current epoch. * If an epoch might have passed since the last update(), you * should call update(0, @a ratenum) before calling this * function. */ inline int rate(unsigned ratenum = 0) const; /** @brief Update the sample count for the current epoch. * @param delta increment for current epoch sample count * @param ratenum rate index (0 <= ratenum < rate_count) * @note If the epoch has changed since the last update(), * this function applies the last epoch's sample count (if any) * to the relevant moving average, accounts for any passage of * time (in case one or more epochs have passed with no samples), * and clears the sample count for the new epoch. */ inline void update(signed_value_type delta, unsigned ratenum = 0); /** @brief Unparse the current average into a String. * @param ratenum rate index (0 <= ratenum < rate_count) * @note The returned value is unscaled, but may contain a fractional * part. * @note unparse_rate() does not check the current epoch. * If an epoch might have passed since the last update(), you * should call update(0, @a ratenum) before calling this * function. */ String unparse_rate(unsigned ratenum = 0) const; private: unsigned _current_epoch; value_type _current[P::rate_count]; DirectEWMAX

_avg[P::rate_count]; inline void update_time(unsigned now); }; /** @class RateEWMAXParameters include/click/ewma.hh * @brief Parameters for a RateEWMA with constant scaling factor * and alpha, one rate count, and epochs of jiffies. * * The RateEWMAXParameters template class is used as a template argument * to RateEWMAX. It defines a EWMA with fixed constant scaling factor and * alpha and one rate count. The EWMA uses jiffies as epochs. Template * parameters are as for DirectEWMAXParameters. * * Example: RateEWMAX@ * @> defines a rate EWMA with user-settable alpha (stability shift) * initially equal to 1/16, scaling factor 10, and value type unsigned. */ template class RateEWMAXParameters : public FixedEWMAXParameters { public: enum { rate_count = 1 }; /** @brief Return the current epoch number. * @note RateEWMAXParameters measures epochs in jiffies. */ static unsigned epoch() { return click_jiffies(); } /** @brief Return the number of epochs (jiffies) per second. */ static unsigned epoch_frequency() { return CLICK_HZ; } }; /** @brief A RateEWMAX with stability shift 4 (alpha 1/16), scaling factor 10 * (10 bits of fraction), one rate, and underlying type unsigned * that measures epochs in jiffies. */ typedef RateEWMAX > RateEWMA; template inline void RateEWMAX

::update_time(unsigned now) { unsigned jj = _current_epoch; if (now != jj) { for (unsigned i = 0; i < P::rate_count; i++) { // adjust the average rate using the last measured packets _avg[i].update(_current[i]); // adjust for time w/ no packets if (jj + 1 != now) _avg[i].update_n(0, now - jj - 1); _current[i] = 0; } _current_epoch = now; } } template inline void RateEWMAX

::update(signed_value_type delta, unsigned ratenum) { update_time(P::epoch()); _current[ratenum] += delta; } template inline int RateEWMAX

::rate(unsigned ratenum) const { return (scaled_average(ratenum) * P::epoch_frequency()) >> _avg[ratenum].scale(); } template inline String RateEWMAX

::unparse_rate(unsigned ratenum) const { return cp_unparse_real2(scaled_average(ratenum) * P::epoch_frequency(), _avg[ratenum].scale()); } CLICK_ENDDECLS #endif