java.lang.Object
net.i2p.stat.Frequency

public class Frequencyextends Object
Manage the calculation of a moving average event frequency over a certain period.

This provides lifetime, and rolling average, frequency counts. Unlike Rate, it does not support "bucketed" averages. There is no tracking of the event frequency in the current or last bucket. There are no buckets at all.

Depending on what you want, a rolling average might be better than buckets. Or not.

  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    private double
    Average interval between recent events, in ms.
    private long
    Events counted so far.
    private long
    When the most recent event happened.
    private double
    Smallest average interval seen in the period.
    private final long
    How far back events count, in ms.
    private final long
    When this frequency was created.
  • Constructor Summary

    Constructors
    Constructor
    Description
    Frequency(long period)
    Creates a new Frequency with the specified period.
  • Method Summary

    Modifier and Type
    Method
    Description
    void
    Take note that a new event occurred, recalculating all the averages and frequencies.
    double
    Calculate how many events would occur in a period given the current (rolling) average.
    double
    On average over the last $period, after how many milliseconds are events coming in, as calculated during the last event occurrence?
    long
    How many events have occurred within the lifetime of this stat?
    double
    Calculate how many events would occur in a period given the maximum rolling average.
    double
    What is the lowest average interval (aka most frequent) we have seen? (ms).
    long
    How long is this frequency averaged over? (ms).
    double
    Using the strict average interval, how many events occur within an average period?
    double
    Over the lifetime of this stat, without any decay or weighting, what was the average interval between events? (ms).
    private static final long
    now()
    Reads the current time.
    void
    Recalculate the averages.
    private void
    recalculate(boolean eventOccurred)
    Recalculate, but only update the lastEvent if eventOccurred
    (package private) void
    Appends the data of this frequency to the specified StringBuilder.

    Methods inherited from class Object

    clone, equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

    • _avgInterval

      private double _avgInterval
      Average interval between recent events, in ms.
    • _minAverageInterval

      private double _minAverageInterval
      Smallest average interval seen in the period.
    • _period

      private final long _period
      How far back events count, in ms.
    • _lastEvent

      private long _lastEvent
      When the most recent event happened.
    • _start

      private final long _start
      When this frequency was created.
    • _count

      private long _count
      Events counted so far.
  • Constructor Details

    • Frequency

      public Frequency(long period)
      Creates a new Frequency with the specified period.
      Parameters:
      period - the length of one period in milliseconds, the window over which events are averaged
  • Method Details

    • getPeriod

      public long getPeriod()
      How long is this frequency averaged over? (ms).
      Returns:
      the period in ms
    • getAverageInterval

      public double getAverageInterval()
      On average over the last $period, after how many milliseconds are events coming in, as calculated during the last event occurrence?
      Returns:
      milliseconds; returns period + 1 if no events in previous period
    • getMinAverageInterval

      public double getMinAverageInterval()
      What is the lowest average interval (aka most frequent) we have seen? (ms).
      Returns:
      milliseconds; returns period + 1 if no events in previous period
    • getAverageEventsPerPeriod

      public double getAverageEventsPerPeriod()
      Calculate how many events would occur in a period given the current (rolling) average. Use getStrictAverageInterval() for the real lifetime average.
      Returns:
      the average events per period
    • getMaxAverageEventsPerPeriod

      public double getMaxAverageEventsPerPeriod()
      Calculate how many events would occur in a period given the maximum rolling average. Use getStrictAverageEventsPerPeriod() for the real lifetime average.
      Returns:
      the max average events per period
    • getStrictAverageInterval

      public double getStrictAverageInterval()
      Over the lifetime of this stat, without any decay or weighting, what was the average interval between events? (ms).
      Returns:
      milliseconds; returns Double.MAX_VALUE if no events ever
    • getStrictAverageEventsPerPeriod

      public double getStrictAverageEventsPerPeriod()
      Using the strict average interval, how many events occur within an average period?
      Returns:
      events per period
    • getEventCount

      public long getEventCount()
      How many events have occurred within the lifetime of this stat?
      Returns:
      event count since this stat was created
    • eventOccurred

      public void eventOccurred()
      Take note that a new event occurred, recalculating all the averages and frequencies.
    • recalculate

      public void recalculate()
      Recalculate the averages.
    • recalculate

      private void recalculate(boolean eventOccurred)
      Recalculate, but only update the lastEvent if eventOccurred

      The clock read is taken before the monitor, not inside it. It is a leaf call - currentTimeMillis is served from the vDSO and takes no Java lock - so holding this monitor across it makes every concurrent event queue behind a syscall rather than behind arithmetic. Hoisting it out cuts the contended cost of FrequencyStat.eventOccurred() on a three-period stat from 166ns to 145ns per event; uncontended it changes nothing, because the clock read costs the same either way when there is no queue.

      It is also safe to move. now is only ever differenced against _lastEvent, which is still read and written under the monitor, so the only effect is that the thread which loses the race computes its interval from a timestamp a few nanoseconds older. At millisecond resolution, and with the interval already clamped to [1, _period], that is not observable.

      Parameters:
      eventOccurred - true to record an event: the last-event time is updated and the count incremented; false recalculates the average interval only
    • now

      private static final long now()
      Reads the current time.
      Returns:
      the current time, in ms
    • store

      void store(StringBuilder dest)
      Appends the data of this frequency to the specified StringBuilder.
      Parameters:
      dest - to append data to