Class SmoothRateLimiter.SmoothWarmingUp

Enclosing class:
SmoothRateLimiter

static final class SmoothRateLimiter.SmoothWarmingUp extends SmoothRateLimiter
This implements the following function where coldInterval = coldFactor * stableInterval.
          ^ throttling
          |
    cold  +                  /
 interval |                 /.
          |                / .
          |               /  .   ← "warmup period" is the area of the trapezoid between
          |              /   .     thresholdPermits and maxPermits
          |             /    .
          |            /     .
          |           /      .
   stable +----------/  WARM .
 interval |          .   UP  .
          |          . PERIOD.
          |          .       .
        0 +----------+-------+--------------→ storedPermits
          0 thresholdPermits maxPermits
 
Before going into the details of this particular function, let's keep in mind the basics:
  1. The state of the RateLimiter (storedPermits) is a vertical line in this figure.
  2. When the RateLimiter is not used, this goes right (up to maxPermits)
  3. When the RateLimiter is used, this goes left (down to zero), since if we have storedPermits, we serve from those first
  4. When _unused_, we go right at a constant rate! The rate at which we move to the right is chosen as maxPermits / warmupPeriod. This ensures that the time it takes to go from 0 to maxPermits is equal to warmupPeriod.
  5. When _used_, the time it takes, as explained in the introductory class note, is equal to the integral of our function, between X permits and X-K permits, assuming we want to spend K saved permits.

In summary, the time it takes to move to the left (spend K permits), is equal to the area of the function of width == K.

Assuming we have saturated demand, the time to go from maxPermits to thresholdPermits is equal to warmupPeriod. And the time to go from thresholdPermits to 0 is warmupPeriod/2. (The reason that this is warmupPeriod/2 is to maintain the behavior of the original implementation where coldFactor was hard coded as 3.)

It remains to calculate thresholdsPermits and maxPermits.

  • The time to go from thresholdPermits to 0 is equal to the integral of the function between 0 and thresholdPermits. This is thresholdPermits * stableIntervals. By (5) it is also equal to warmupPeriod/2. Therefore
    thresholdPermits = 0.5 * warmupPeriod / stableInterval
  • The time to go from maxPermits to thresholdPermits is equal to the integral of the function between thresholdPermits and maxPermits. This is the area of the pictured trapezoid, and it is equal to 0.5 * (stableInterval + coldInterval) * (maxPermits - thresholdPermits). It is also equal to warmupPeriod, so
    maxPermits = thresholdPermits + 2 * warmupPeriod / (stableInterval + coldInterval)
  • Field Details

    • warmupPeriodMicros

      private final long warmupPeriodMicros
    • slope

      private double slope
      The slope of the line from the stable interval (when permits == 0), to the cold interval (when permits == maxPermits)
    • thresholdPermits

      private double thresholdPermits
    • coldFactor

      private double coldFactor
  • Constructor Details

  • Method Details

    • doSetRate

      void doSetRate(double permitsPerSecond, double stableIntervalMicros)
      Specified by:
      doSetRate in class SmoothRateLimiter
    • storedPermitsToWaitTime

      long storedPermitsToWaitTime(double storedPermits, double permitsToTake)
      Description copied from class: SmoothRateLimiter
      Translates a specified portion of our currently stored permits which we want to spend/acquire, into a throttling time. Conceptually, this evaluates the integral of the underlying function we use, for the range of [(storedPermits - permitsToTake), storedPermits].

      This always holds: 0 <= permitsToTake <= storedPermits

      Specified by:
      storedPermitsToWaitTime in class SmoothRateLimiter
    • permitsToTime

      private double permitsToTime(double permits)
    • coolDownIntervalMicros

      double coolDownIntervalMicros()
      Description copied from class: SmoothRateLimiter
      Returns the number of microseconds during cool down that we have to wait to get a new permit.
      Specified by:
      coolDownIntervalMicros in class SmoothRateLimiter