8
8
9
9
"github.com/platinummonkey/go-concurrency-limits/core"
10
10
"github.com/platinummonkey/go-concurrency-limits/limit/functions"
11
+ "github.com/platinummonkey/go-concurrency-limits/measurements"
11
12
)
12
13
13
14
// VegasLimit implements a Limiter based on TCP Vegas where the limit increases by alpha if the queue_use is
@@ -21,7 +22,7 @@ import (
21
22
type VegasLimit struct {
22
23
estimatedLimit float64
23
24
maxLimit int
24
- rttNoLoad int64
25
+ rttNoLoad core. MeasurementInterface
25
26
smoothing float64
26
27
alphaFunc func (estimatedLimit int ) int
27
28
betaFunc func (estimatedLimit int ) int
@@ -31,7 +32,8 @@ type VegasLimit struct {
31
32
rttSampleListener core.MetricSampleListener
32
33
commonSampler * core.CommonMetricSampler
33
34
probeMultipler int
34
- probeCountdown int
35
+ probeJitter float64
36
+ probeCount int64
35
37
36
38
listeners []core.LimitChangeListener
37
39
registry core.MetricRegistry
@@ -49,6 +51,7 @@ func NewDefaultVegasLimit(
49
51
return NewVegasLimitWithRegistry (
50
52
name ,
51
53
- 1 ,
54
+ nil ,
52
55
- 1 ,
53
56
- 1 ,
54
57
nil ,
@@ -74,6 +77,7 @@ func NewDefaultVegasLimitWithLimit(
74
77
return NewVegasLimitWithRegistry (
75
78
name ,
76
79
initialLimit ,
80
+ nil ,
77
81
- 1 ,
78
82
- 1 ,
79
83
nil ,
@@ -92,6 +96,7 @@ func NewDefaultVegasLimitWithLimit(
92
96
func NewVegasLimitWithRegistry (
93
97
name string ,
94
98
initialLimit int ,
99
+ rttNoLoad core.MeasurementInterface ,
95
100
maxConcurrency int ,
96
101
smoothing float64 ,
97
102
alphaFunc func (estimatedLimit int ) int ,
@@ -107,12 +112,19 @@ func NewVegasLimitWithRegistry(
107
112
if initialLimit < 1 {
108
113
initialLimit = 20
109
114
}
115
+
116
+ if rttNoLoad == nil {
117
+ rttNoLoad = & measurements.MinimumMeasurement {}
118
+ }
119
+
110
120
if maxConcurrency < 0 {
111
121
maxConcurrency = 1000
112
122
}
123
+
113
124
if smoothing < 0 || smoothing > 1.0 {
114
125
smoothing = 1.0
115
126
}
127
+
116
128
if probeMultiplier <= 0 {
117
129
probeMultiplier = 30
118
130
}
@@ -163,7 +175,9 @@ func NewVegasLimitWithRegistry(
163
175
decreaseFunc : decreaseFunc ,
164
176
smoothing : smoothing ,
165
177
probeMultipler : probeMultiplier ,
166
- probeCountdown : nextVegasProbeCountdown (probeMultiplier , float64 (initialLimit )),
178
+ probeJitter : newProbeJitter (),
179
+ probeCount : 0 ,
180
+ rttNoLoad : rttNoLoad ,
167
181
rttSampleListener : registry .RegisterDistribution (core .PrefixMetricWithName (core .MetricMinRTT , name ), tags ... ),
168
182
listeners : make ([]core.LimitChangeListener , 0 ),
169
183
registry : registry ,
@@ -174,12 +188,11 @@ func NewVegasLimitWithRegistry(
174
188
return l
175
189
}
176
190
177
- // LimitProbeDisabled represents the disabled value for probing.
178
- const LimitProbeDisabled = - 1
191
+ // ProbeDisabled represents the disabled value for probing.
192
+ const ProbeDisabled = - 1
179
193
180
- func nextVegasProbeCountdown (probeMultiplier int , estimatedLimit float64 ) int {
181
- maxRange := int (float64 (probeMultiplier )* estimatedLimit ) / 2
182
- return rand .Intn (maxRange ) + maxRange // return roughly [maxVal / 2, maxVal]
194
+ func newProbeJitter () float64 {
195
+ return (rand .Float64 () / 2.0 ) + 0.5
183
196
}
184
197
185
198
// EstimatedLimit returns the current estimated limit.
@@ -209,28 +222,32 @@ func (l *VegasLimit) OnSample(startTime int64, rtt int64, inFlight int, didDrop
209
222
defer l .mu .Unlock ()
210
223
l .commonSampler .Sample (rtt , inFlight , didDrop )
211
224
212
- if l . probeCountdown != LimitProbeDisabled {
213
- l . probeCountdown --
214
- if l . probeCountdown <= 0 {
215
- l . logger . Debugf ( "probe MinRTT %d" , rtt / 1e6 )
216
- l . probeCountdown = nextVegasProbeCountdown ( l . probeMultipler , l . estimatedLimit )
217
- l . rttNoLoad = rtt
218
- return
219
- }
225
+ l . probeCount ++
226
+ if l . shouldProbe () {
227
+ l . logger . Debugf ( "Probe triggered update to RTT No Load %d ms from %d ms" ,
228
+ rtt / 1e6 , int64 ( l . rttNoLoad . Get ()) / 1e6 )
229
+ l . probeJitter = newProbeJitter ( )
230
+ l . probeCount = 0
231
+ l . rttNoLoad . Add ( float64 ( rtt ))
232
+ return
220
233
}
221
234
222
- if l .rttNoLoad == 0 || rtt < l .rttNoLoad {
223
- l .logger .Debugf ("New MinRTT %d " , rtt / 1e6 )
224
- l .rttNoLoad = rtt
235
+ if l .rttNoLoad . Get () == 0 || float64 ( rtt ) < l .rttNoLoad . Get () {
236
+ l .logger .Debugf ("Update RTT No Load to %d ms from %d ms " , rtt / 1e6 , int64 ( l . rttNoLoad . Get ()) / 1e6 )
237
+ l .rttNoLoad . Add ( float64 ( rtt ))
225
238
return
226
239
}
227
240
228
- l .rttSampleListener .AddSample (float64 ( l .rttNoLoad ))
241
+ l .rttSampleListener .AddSample (l .rttNoLoad . Get ( ))
229
242
l .updateEstimatedLimit (startTime , rtt , inFlight , didDrop )
230
243
}
231
244
245
+ func (l * VegasLimit ) shouldProbe () bool {
246
+ return int64 (l .probeJitter * float64 (l .probeMultipler )* l .estimatedLimit ) <= l .probeCount
247
+ }
248
+
232
249
func (l * VegasLimit ) updateEstimatedLimit (startTime int64 , rtt int64 , inFlight int , didDrop bool ) {
233
- queueSize := int (math .Ceil (l .estimatedLimit * (1 - float64 ( l .rttNoLoad )/ float64 (rtt ))))
250
+ queueSize := int (math .Ceil (l .estimatedLimit * (1 - l .rttNoLoad . Get ( )/ float64 (rtt ))))
234
251
235
252
var newLimit float64
236
253
// Treat any drop (i.e timeout) as needing to reduce the limit
@@ -264,7 +281,7 @@ func (l *VegasLimit) updateEstimatedLimit(startTime int64, rtt int64, inFlight i
264
281
265
282
if int (newLimit ) != int (l .estimatedLimit ) && l .logger .IsDebugEnabled () {
266
283
l .logger .Debugf ("New limit=%d, minRTT=%d ms, winRTT=%d ms, queueSize=%d" ,
267
- int (newLimit ), l .rttNoLoad / 1e6 , rtt / 1e6 , queueSize )
284
+ int (newLimit ), int64 ( l .rttNoLoad . Get ()) / 1e6 , rtt / 1e6 , queueSize )
268
285
}
269
286
270
287
l .estimatedLimit = newLimit
@@ -275,7 +292,7 @@ func (l *VegasLimit) updateEstimatedLimit(startTime int64, rtt int64, inFlight i
275
292
func (l * VegasLimit ) RTTNoLoad () int64 {
276
293
l .mu .RLock ()
277
294
defer l .mu .RUnlock ()
278
- return l .rttNoLoad
295
+ return int64 ( l .rttNoLoad . Get ())
279
296
}
280
297
281
298
func (l * VegasLimit ) String () string {
0 commit comments