Skip to content

Commit

Permalink
rate: Avoid precision loss with edge cases
Browse files Browse the repository at this point in the history
When burst is 1, there would be edge cases we get tokens of 0.9999999999997222
due to float64 multiplication/division rounding out value. So avoid those
calculation when 'last' is old enough

Fixes golang/go#46579
  • Loading branch information
linxiulei committed Jun 4, 2021
1 parent f8bda1e commit 81b70a9
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 2 deletions.
4 changes: 2 additions & 2 deletions rate/rate.go
Original file line number Diff line number Diff line change
Expand Up @@ -370,8 +370,8 @@ func (lim *Limiter) advance(now time.Time) (newNow time.Time, newLast time.Time,
// Avoid making delta overflow below when last is very old.
maxElapsed := lim.limit.durationFromTokens(float64(lim.burst) - lim.tokens)
elapsed := now.Sub(last)
if elapsed > maxElapsed {
elapsed = maxElapsed
if elapsed >= maxElapsed {
return now, last, float64(lim.burst)
}

// Calculate the new number of tokens, due to time that passed.
Expand Down
8 changes: 8 additions & 0 deletions rate/rate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -476,3 +476,11 @@ func BenchmarkWaitNNoDelay(b *testing.B) {
lim.WaitN(ctx, 1)
}
}

func TestPreciseAllow(t *testing.T) {
lim := NewLimiter(0.00027777777777777778, 1)
lim.tokens = 0.54990492004805558
if !lim.Allow() {
t.Errorf("want ok, got false")
}
}

0 comments on commit 81b70a9

Please sign in to comment.