Class SmoothRateLimiter.SmoothWarmingUp
- java.lang.Object
-
- com.google.common.util.concurrent.RateLimiter
-
- com.google.common.util.concurrent.SmoothRateLimiter
-
- com.google.common.util.concurrent.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:- The state of the RateLimiter (storedPermits) is a vertical line in this figure.
- When the RateLimiter is not used, this goes right (up to maxPermits)
- When the RateLimiter is used, this goes left (down to zero), since if we have storedPermits, we serve from those first
- 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.
- 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)
-
-
Nested Class Summary
-
Nested classes/interfaces inherited from class com.google.common.util.concurrent.SmoothRateLimiter
SmoothRateLimiter.SmoothBursty, SmoothRateLimiter.SmoothWarmingUp
-
Nested classes/interfaces inherited from class com.google.common.util.concurrent.RateLimiter
RateLimiter.SleepingStopwatch
-
-
Field Summary
Fields Modifier and Type Field Description private double
coldFactor
private double
slope
The slope of the line from the stable interval (when permits == 0), to the cold interval (when permits == maxPermits)private double
thresholdPermits
private long
warmupPeriodMicros
-
Fields inherited from class com.google.common.util.concurrent.SmoothRateLimiter
maxPermits, stableIntervalMicros, storedPermits
-
-
Constructor Summary
Constructors Constructor Description SmoothWarmingUp(RateLimiter.SleepingStopwatch stopwatch, long warmupPeriod, java.util.concurrent.TimeUnit timeUnit, double coldFactor)
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description (package private) double
coolDownIntervalMicros()
Returns the number of microseconds during cool down that we have to wait to get a new permit.(package private) void
doSetRate(double permitsPerSecond, double stableIntervalMicros)
private double
permitsToTime(double permits)
(package private) long
storedPermitsToWaitTime(double storedPermits, double permitsToTake)
Translates a specified portion of our currently stored permits which we want to spend/acquire, into a throttling time.-
Methods inherited from class com.google.common.util.concurrent.SmoothRateLimiter
doGetRate, doSetRate, queryEarliestAvailable, reserveEarliestAvailable, resync
-
Methods inherited from class com.google.common.util.concurrent.RateLimiter
acquire, acquire, create, create, create, create, create, getRate, reserve, reserveAndGetWaitLength, setRate, toString, tryAcquire, tryAcquire, tryAcquire, tryAcquire, tryAcquire, tryAcquire
-
-
-
-
Field Detail
-
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 Detail
-
SmoothWarmingUp
SmoothWarmingUp(RateLimiter.SleepingStopwatch stopwatch, long warmupPeriod, java.util.concurrent.TimeUnit timeUnit, double coldFactor)
-
-
Method Detail
-
doSetRate
void doSetRate(double permitsPerSecond, double stableIntervalMicros)
- Specified by:
doSetRate
in classSmoothRateLimiter
-
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 classSmoothRateLimiter
-
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 classSmoothRateLimiter
-
-