java.lang.Object
net.i2p.router.tunnel.RateStatMeanBatch

class RateStatMeanBatchextends Object
Accumulates samples of a mean rate stat and emits one addRateData per flush, so a hot path that samples a level once per message or per 1KB fragment pays one stat lookup and one monitor per rate period instead of one per sample.

Which statistics may be batched this way is a semantic question, not a performance one, and this class only answers it for one kind of stat. Rate.addData(long) accumulates a total and an event count per period, and every reader divides them:

  • A mean stat — one that samples a level (queue depth, fragments per message, write delay) — is read as total / eventCount. N samples of v therefore report the mean of those samples, and collapsing them into one sample of that mean leaves the reported quantity the same up to the weighting (samples per flush rather than samples per period). That is what this class is for.
  • An event counter stat — addRateData(name, 1) per event — cannot be batched here at all: collapsing N events into one sample would make the period's event count report flushes rather than events, and Rate.getLastEventCount() feeds adaptive tuning. Such a stat has to resolve a RateStat handle once and call addData per event instead.

Safe for concurrent add(long): producers accumulate into LongAdders and only the flushing thread resets them, so a sample can straddle a flush boundary — which for a mean only moves one sample from one period to the next. Both flush methods drain the sample count first, for a reason worth stating: the count is what decides whether there is anything to emit, so resetting it first is what keeps a value sum from outliving its own count. Draining the sums first would let a sample whose count lands in this window but whose value lands in the next one leave a stale value behind with no count to ever flush it, contaminating the mean of some later flush. As written, every value added is consumed by exactly one flush, and a boundary-straddling sample is emitted as a zero for the following flush — an under-report by one sample, which is the direction the truncation contract already accepts.

  • Constructor Summary

    Constructors
    Constructor
    Description
    Start with no pending samples.
  • Method Summary

    Modifier and Type
    Method
    Description
    (package private) void
    add(long value)
    Sample a level with no event duration.
    (package private) void
    add(long value, long eventDuration)
    Sample a level together with an event duration (the weight the rate counts alongside the value).
    (package private) boolean
    Emit one sample covering everything accumulated so far and start over.
    (package private) boolean
    As flush(RouterContext, String), but records the accumulated event durations against the rate as well.
    (package private) long
    Mean of the durations sampled since the last flush, truncated toward zero.
    (package private) static long
    meanOf(long sum, long count)
    Divide, guarding the empty batch.
    (package private) long
    Mean of the values sampled since the last flush, truncated toward zero.
    (package private) long
    Samples accumulated since the last flush.
    (package private) void
    Drop everything accumulated so far.

    Methods inherited from class Object

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

    • RateStatMeanBatch

      RateStatMeanBatch()
      Start with no pending samples.
  • Method Details

    • add

      void add(long value)
      Sample a level with no event duration.
      Parameters:
      value - the sampled level
    • add

      void add(long value, long eventDuration)
      Sample a level together with an event duration (the weight the rate counts alongside the value).
      Parameters:
      value - the sampled level
      eventDuration - weight recorded with the value, 0 for none
    • pendingCount

      long pendingCount()
      Samples accumulated since the last flush.
      Returns:
      the number of unflushed samples
    • meanValue

      long meanValue()
      Mean of the values sampled since the last flush, truncated toward zero.
      Returns:
      the mean sampled value, 0 when nothing is pending
    • meanEventDuration

      long meanEventDuration()
      Mean of the durations sampled since the last flush, truncated toward zero.
      Returns:
      the mean event duration, 0 when nothing is pending
    • meanOf

      static long meanOf(long sum, long count)
      Divide, guarding the empty batch.

      Integer division, so a mean is truncated toward zero: the error is always in [0, 1) of a unit. Under one unit, never a unit in the over-reporting direction — on a quantity that was never more precise than its integer samples. Rounding would let a stat claiming to never over-report a queue depth or a write delay do exactly that.

      Parameters:
      sum - the accumulated samples
      count - how many samples were accumulated
      Returns:
      the mean, or 0 when count is zero
    • flush

      boolean flush(RouterContext ctx, String name)
      Emit one sample covering everything accumulated so far and start over. Emits nothing when no sample is pending, because a zero-valued sample would still raise the rate's event count and pull its average down.
      Parameters:
      ctx - the router context
      name - the stat to emit into
      Returns:
      true if a sample was emitted
    • flushWithEventDuration

      boolean flushWithEventDuration(RouterContext ctx, String name)
      As flush(RouterContext, String), but records the accumulated event durations against the rate as well. Use only where the call sites being collapsed passed a duration, so the rate's event time keeps the same meaning.
      Parameters:
      ctx - the router context
      name - the stat to emit into
      Returns:
      true if a sample was emitted
    • reset

      void reset()
      Drop everything accumulated so far.