/// <summary> /// <para> /// The returned <code>RateLimiter</code> is intended for cases where the resource that actually /// fulfills the requests (e.g., a remote server) needs "warmup" time, rather than /// being immediately accessed at the stable (maximum) rate. /// </para> /// <para> /// The returned <code>RateLimiter</code> starts in a "cold" state (i.e. the warmup period /// will follow), and if it is left unused for long enough, it will return to that state. /// </para> /// </summary> /// <param name="permitsPerSecond">The rate of the returned <code>RateLimiter</code>, measured in how many permits become available per second</param> /// <param name="warmupPeriod">The duration of the period where the <code>RateLimiter</code> ramps up its rate, before reaching its stable (maximum) rate</param> /// <param name="unit">The time unit of the warmupPeriod argument</param> /// <param name="coldFactor"></param> public static RateLimiter Create(double permitsPerSecond, long warmupPeriod, TimeUnit unit = TimeUnit.Seconds, double coldFactor = 3.0) { if (warmupPeriod < 0) { throw new ArgumentOutOfRangeException(nameof(warmupPeriod), "WarmupPeriod must not be negative"); } return(Create(SleepingStopwatch.CreateFromSystemTimer(), permitsPerSecond, warmupPeriod, unit, coldFactor)); }
/// <summary> /// Creates a <code>RateLimiter</code> with the specified stable throughput, given as "permits per second" /// </summary> /// <remarks> /// Creates a <code>RateLimiter</code> with the specified stable throughput, given as /// "permits per second" (commonly referred to as QPS, queries per second). /// /// The returned <code>RateLimiter</code> ensures that on average no more than <code>permitsPerSecond</code> /// are issued during any given second, with sustained requests /// being smoothly spread over each second. When the incoming request rate exceeds /// <code>permitsPerSecond</code> the rate limiter will release one permit every /// <code>(1.0 / permitsPerSecond)</code> seconds. When the rate limiter is unused, /// bursts of up to <code>permitsPerSecond</code> permits will be allowed, with subsequent /// requests being smoothly limited at the stable rate of <code>permitsPerSecond</code>. /// </remarks> /// <param name="permitsPerSecond"> /// The rate of the returned <code>RateLimiter</code>, measured in how many permits become available per second /// </param> public static RateLimiter Create(double permitsPerSecond) { /* The default RateLimiter configuration can save the unused permits of up to one second. * This is to avoid unnecessary stalls in situations like this: A RateLimiter of 1qps, * and 4 threads, all calling acquire() at these moments: * * T0 at 0 seconds * T1 at 1.05 seconds * T2 at 2 seconds * T3 at 3 seconds * * Due to the slight delay of T1, T2 would have to sleep till 2.05 seconds, * and T3 would also have to sleep till 3.05 seconds. */ return(Create(SleepingStopwatch.CreateFromSystemTimer(), permitsPerSecond)); }