Class ExponentiallyWeightedMovingRate

java.lang.Object
org.elasticsearch.common.metrics.ExponentiallyWeightedMovingRate

public class ExponentiallyWeightedMovingRate extends Object
Implements a version of an exponentially weighted moving rate (EWMR). This is a calculation over a finite time series of increments to some sort of gauge or counter which gives a value for the rate at which the gauge is being incremented where the weight given to an increment decreases exponentially with how long ago it happened.

Definitions: The rate of increase of the gauge or counter over an interval is the sum of the increments which occurred during the interval, divided by the length of the interval. The weighted rate of increase is the sum of the increments with each multiplied by a weight which is a function of how long ago it happened, divided by the integral of the weight function over the interval. The exponentially weighted rate is the weighted rate when the weight function is given by exp(-1.0 * lambda * time) where lambda is a constant and time specifies how long ago the increment happened. A moving rate is simply a rate calculated for an every-growing series of increments (typically by updating the previous rate rather than recalculating from scratch).

The times involved in the API of this class can use the caller's choice of units and origin, e.g. they can be millis since the epoch as returned by System.currentTimeMillis(), nanos since an arbitrary origin as returned by System.nanoTime(), or anything else. The only requirement is that the same convention must be used consistently.

This class is thread-safe.

  • Constructor Summary

    Constructors
    Constructor
    Description
    ExponentiallyWeightedMovingRate(double lambda, long startTime)
    Constructor.
  • Method Summary

    Modifier and Type
    Method
    Description
    void
    addIncrement(double increment, long time)
    Updates the rate to reflect that the gauge has been incremented by an amount increment at a time time.
    double
    calculateRateSince(long currentTime, double currentRate, long oldTime, double oldRate)
    Given the EWMR currentRate at time currentTime and the EWMR oldRate at time oldTime, returns the EWMR that would be calculated at currentTime if the start time was oldTime rather than the startTime passed to the parameter.
    double
    Returns the configured half-life of this instance.
    double
    getRate(long time)
    Returns the EWMR at the given time.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Constructor Details

    • ExponentiallyWeightedMovingRate

      public ExponentiallyWeightedMovingRate(double lambda, long startTime)
      Constructor.
      Parameters:
      lambda - A parameter which dictates how quickly the average "forgets" older increments. The weight given to an increment which happened time timeAgo ago will be proportional to exp(-1.0 * lambda * timeAgo). The half-life is related to this parameter by the equation exp(-1.0 * lambda * halfLife) = 0.5}, so lambda = log(2.0) / halfLife). This may be zero, but must not be negative. The units of this value are the inverse of the units being used for time.
      startTime - The time to consider the start time for the rate calculation. This must be greater than zero. The units and origin of this value must match all other calls to this instance.
  • Method Details

    • getRate

      public double getRate(long time)
      Returns the EWMR at the given time. The units and origin of this time must match all other calls to this instance. The units of the returned rate are the ratio of the increment units to the time units as used for addIncrement(double, long).

      If there have been no increments yet, this returns zero.

      Otherwise, we require the time to be no earlier than the time of the previous increment, i.e. the value of time for this call must not be less than the value of time for the last call to addIncrement(double, long). If this is not the case, the method behaves as if it had that minimum value.

    • calculateRateSince

      public double calculateRateSince(long currentTime, double currentRate, long oldTime, double oldRate)
      Given the EWMR currentRate at time currentTime and the EWMR oldRate at time oldTime, returns the EWMR that would be calculated at currentTime if the start time was oldTime rather than the startTime passed to the parameter. This rate incorporates all the increments that contributed to currentRate but not to oldRate. The increments that contributed to oldRate are effectively 'forgotten'. The units and origin of the times and rates must match all other calls to this instance.

      Normally, currentTime should be after oldTime. If it is not, this method returns zero.

      Note that this method does not depend on any of the increments made to this ExponentiallyWeightedMovingRate instance. It is only non-static because it uses this instance's lambda and startTime.

    • addIncrement

      public void addIncrement(double increment, long time)
      Updates the rate to reflect that the gauge has been incremented by an amount increment at a time time. The unit and offset of the time must match all other calls to this instance. The units of the increment are arbitrary but must also be consistent.

      If this is the first increment, we require it to occur after the start time for the rate calculation, i.e. the value of time must be greater than startTime passed to the constructor. If this is not the case, the method behaves as if time is startTime + 1 to prevent a division by zero error.

      If this is not the first increment, we require it not to occur before the previous increment, i.e. the value of time for this call must be greater than or equal to the value for the previous call. If this is not the case, the method behaves as if this call's time is the same as the previous call's.

    • getHalfLife

      public double getHalfLife()
      Returns the configured half-life of this instance. The units are the same as all other times in API calls, and the inverse of the units used for the lambda constructor parameter. If lambda is 0.0, returns Double.POSITIVE_INFINITY.