Skip to content

Commit 128bf38

Browse files
authored
AIMD optimizations and tests (#29)
1 parent 1cfed02 commit 128bf38

File tree

6 files changed

+976
-100
lines changed

6 files changed

+976
-100
lines changed

aimd.go

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@ import (
1414
// similar to the congestion control algorithm used in TCP.
1515
type AIMDTokenBucketLimiter struct {
1616
limiter *TokenBucketLimiter
17-
rates atomicSliceInt64 // Per-bucket rates in tokens per second
18-
rateMin int64 // Minimum rate (tokens per unit)
19-
rateMax int64 // Maximum rate (tokens per unit)
20-
rateAI int64 // Additive increase (tokens per unit)
21-
rateMD float64 // Multiplicative decrease (multiplier)
22-
rateUnit time.Duration // Time unit for rate calculations
17+
rates atomicSliceFloat64 // Per-bucket rates in tokens per unit
18+
rateMin float64 // Minimum rate (tokens per unit)
19+
rateMax float64 // Maximum rate (tokens per unit)
20+
rateAI float64 // Additive increase (tokens per unit)
21+
rateMD float64 // Multiplicative decrease (multiplier)
22+
rateUnit time.Duration // Time unit for rate calculations
2323
}
2424

2525
// NewAIMDTokenBucketLimiter creates a new AIMD token bucket limiter
@@ -139,18 +139,17 @@ func NewAIMDTokenBucketLimiter(
139139
}
140140
}
141141

142-
rate := nanoRate(rateUnit, rateInit)
143-
rates := newAtomicSliceInt64(limiter.buckets.Len())
142+
rates := newAtomicSliceFloat64(limiter.buckets.Len())
144143
for i := range rates.Len() {
145-
rates.Set(i, rate)
144+
rates.Set(i, rateInit)
146145
}
147146

148147
return &AIMDTokenBucketLimiter{
149148
limiter: limiter,
150149
rates: rates,
151-
rateMin: nanoRate(rateUnit, rateMin),
152-
rateMax: nanoRate(rateUnit, rateMax),
153-
rateAI: nanoRate(rateUnit, rateAdditiveIncrease),
150+
rateMin: rateMin,
151+
rateMax: rateMax,
152+
rateAI: rateAdditiveIncrease,
154153
rateMD: rateMultiplicativeDecrease,
155154
rateUnit: rateUnit,
156155
}, nil
@@ -163,7 +162,8 @@ func NewAIMDTokenBucketLimiter(
163162
func (a *AIMDTokenBucketLimiter) TakeToken(id []byte) bool {
164163
index := a.limiter.index(id)
165164
rate := a.rates.Get(index)
166-
return a.limiter.takeTokenInner(index, rate)
165+
nano := nanoRate(a.rateUnit, rate)
166+
return a.limiter.takeTokenInner(index, nano)
167167
}
168168

169169
// Check returns whether a token would be available for the given ID
@@ -175,7 +175,8 @@ func (a *AIMDTokenBucketLimiter) TakeToken(id []byte) bool {
175175
func (a *AIMDTokenBucketLimiter) Check(id []byte) bool {
176176
index := a.limiter.index(id)
177177
rate := a.rates.Get(index)
178-
return a.limiter.checkInner(index, rate)
178+
nano := nanoRate(a.rateUnit, rate)
179+
return a.limiter.checkInner(index, nano)
179180
}
180181

181182
// IncreaseRate additively increases the rate for the bucket
@@ -192,7 +193,7 @@ func (a *AIMDTokenBucketLimiter) IncreaseRate(id []byte) float64 {
192193
for {
193194
rate := a.rates.Get(index)
194195
if rate == a.rateMax {
195-
return unitRate(a.rateUnit, rate)
196+
return rate
196197
}
197198

198199
next := a.rateMax
@@ -201,11 +202,11 @@ func (a *AIMDTokenBucketLimiter) IncreaseRate(id []byte) float64 {
201202
}
202203

203204
if rate == next {
204-
return unitRate(a.rateUnit, rate)
205+
return rate
205206
}
206207

207208
if a.rates.CompareAndSwap(index, rate, next) {
208-
return unitRate(a.rateUnit, rate)
209+
return rate
209210
}
210211
}
211212
}
@@ -227,16 +228,16 @@ func (a *AIMDTokenBucketLimiter) DecreaseRate(id []byte) float64 {
227228
for {
228229
rate := a.rates.Get(index)
229230
if rate == a.rateMin {
230-
return unitRate(a.rateUnit, rate)
231+
return rate
231232
}
232233

233-
next := max(a.rateMin, a.rateMin+int64(float64(rate-a.rateMin)/a.rateMD))
234+
next := max(a.rateMin, a.rateMin+(rate-a.rateMin)/a.rateMD)
234235
if rate == next {
235-
return unitRate(a.rateUnit, rate)
236+
return rate
236237
}
237238

238239
if a.rates.CompareAndSwap(index, rate, next) {
239-
return unitRate(a.rateUnit, rate)
240+
return rate
240241
}
241242
}
242243
}
@@ -248,6 +249,5 @@ func (a *AIMDTokenBucketLimiter) DecreaseRate(id []byte) float64 {
248249
// goroutines.
249250
func (a *AIMDTokenBucketLimiter) Rate(id []byte) float64 {
250251
index := a.limiter.index(id)
251-
rate := a.rates.Get(index)
252-
return unitRate(a.rateUnit, rate)
252+
return a.rates.Get(index)
253253
}

0 commit comments

Comments
 (0)