@@ -27,13 +27,14 @@ public final class GradientLimit implements Limit {
2727 public static class Builder {
2828 private int initialLimit = 50 ;
2929 private int minLimit = 1 ;
30- private int maxLimit = 1000 ;
30+ private int maxLimit = 200 ;
3131
3232 private double smoothing = 0.2 ;
3333 private Function <Integer , Integer > queueSize = SquareRootFunction .create (4 );
3434 private MetricRegistry registry = EmptyMetricRegistry .INSTANCE ;
3535 private int noLoadRttWindow = 1000 ;
3636 private double noLoadRttFilter = 1.1 ;
37+ private double rttTolerance = 2.0 ;
3738
3839 /**
3940 * Minimum threshold for accepting a new rtt sample. Any RTT lower than this threshold
@@ -76,9 +77,9 @@ public Builder minLimit(int minLimit) {
7677 * before reducing the limit. For example, a value of 2.0 means that a 2x increase in latency is acceptable.
7778 * @return Chainable builder
7879 */
79- @ Deprecated
8080 public Builder rttTolerance (double rttTolerance ) {
8181 Preconditions .checkArgument (rttTolerance >= 1.0 , "Tolerance must be >= 1.0" );
82+ this .rttTolerance = rttTolerance ;
8283 return this ;
8384 }
8485
@@ -209,6 +210,8 @@ public static GradientLimit newDefault() {
209210
210211 private final int minLimit ;
211212
213+ private final double rttTolerance ;
214+
212215 private final Function <Integer , Integer > queueSize ;
213216
214217 private final SampleListener minRttSampleListener ;
@@ -223,6 +226,8 @@ private GradientLimit(Builder builder) {
223226 this .minLimit = builder .minLimit ;
224227 this .queueSize = builder .queueSize ;
225228 this .smoothing = builder .smoothing ;
229+ this .rttTolerance = builder .rttTolerance ;
230+
226231 this .rttNoLoadAccumulator = new ExpAvgMeasurement (builder .noLoadRttWindow , builder .noLoadRttFilter );
227232
228233 this .minRttSampleListener = builder .registry .registerDistribution (MetricIds .MIN_RTT_NAME );
@@ -234,18 +239,18 @@ private GradientLimit(Builder builder) {
234239 public synchronized void update (SampleWindow sample ) {
235240 Preconditions .checkArgument (sample .getCandidateRttNanos () > 0 , "rtt must be >0 but got " + sample .getCandidateRttNanos ());
236241
237- final long rttSample = sample .getCandidateRttNanos ();
242+ final long rttSample = sample .getRttSumNanos () / sample . getSampleCount ();
238243 minWindowRttSampleListener .addSample (rttSample );
239244
240245 final double queueSize = this .queueSize .apply ((int )this .estimatedLimit );
241246 queueSizeSampleListener .addSample (queueSize );
242247
243248 final double rttNoLoad = rttNoLoadAccumulator .add (rttSample ).doubleValue ();
244- final double rtt = (double )rttSample ;
245249
246- minRttSampleListener .addSample (rttNoLoad );
250+ minRttSampleListener .addSample (rttSample );
247251
248252 final double gradient ;
253+ final double rtt = (double )rttSample / rttTolerance ;
249254 // rtt is lower than rtt_noload because of smoothing rtt noload updates
250255 // set to 1.0 to indicate no queueing
251256 if (rtt < rttNoLoad ) {
@@ -264,23 +269,24 @@ public synchronized void update(SampleWindow sample) {
264269 }
265270
266271 // Apply a smoothing factor when reducing the limit only
267- newLimit = (1 -smoothing ) * estimatedLimit + smoothing *(newLimit );
272+ if (newLimit < estimatedLimit ) {
273+ newLimit = (1 -smoothing ) * estimatedLimit + smoothing *(newLimit );
274+ }
275+
268276 newLimit = Math .max (Math .max (minLimit , queueSize ), Math .min (maxLimit , newLimit ));
277+
278+ if (LOG .isDebugEnabled ()) {
279+ LOG .debug ("New limit={} minRtt={} ms winRtt={} ms queueSize={} gradient={}" ,
280+ (int )newLimit ,
281+ TimeUnit .NANOSECONDS .toMicros ((int )rttNoLoad )/1000.0 ,
282+ TimeUnit .NANOSECONDS .toMicros ((int )rttSample )/1000.0 ,
283+ queueSize ,
284+ gradient );
285+ }
269286
270- if ((int )newLimit != (int )estimatedLimit ) {
271- // Don't grow the limit if we are app limited
272- if (sample .getMaxInFlight () + queueSize < estimatedLimit ) {
273- return ;
274- }
275-
276- if (LOG .isDebugEnabled ()) {
277- LOG .debug ("New limit={} minRtt={} ms winRtt={} ms queueSize={} gradient={}" ,
278- (int )newLimit ,
279- TimeUnit .NANOSECONDS .toMicros ((int )rttNoLoad )/1000.0 ,
280- TimeUnit .NANOSECONDS .toMicros ((int )rtt )/1000.0 ,
281- queueSize ,
282- gradient );
283- }
287+ // We are app limited, don't increase the limit to prevent upward drift
288+ if (sample .getMaxInFlight () * 2 < estimatedLimit ) {
289+ return ;
284290 }
285291
286292 estimatedLimit = newLimit ;
0 commit comments