-
Notifications
You must be signed in to change notification settings - Fork 17.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
x/time/rate: float64 precision loss with edge cases #46579
Comments
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
Change https://golang.org/cl/325289 mentions this issue: |
Thanks for reporting. Could you explain how this is related to the loss of precision and why it is expected to work that way? Thanks. |
Would you please also have a look on the PR above? Thanks For the explanation: The 'lim.tokens' may be end up with any value, so 0.54990492004805558 is possible, which was just a case I ran into. Then, say the time has passed a very long period, Allow() should return true. However, in the method 'advance()', we calculate |
I have a bugreport against kubernetes that comes down to this same issue. The repro we boiled down to is below. The referenced patch above (https://golang.org/cl/325289) does fix the repro case. I am not familiar enough with how this lib operates to say if it is exactly correct or is the best fix. So I'm here to +1 the issue and ask for someone in-the-know to consider the patch above. Another repro (let it run 8 loops):
|
Hi everyone. Has anyone had a moment to look at this one? |
@thockin, did @josharian's https://go-review.googlesource.com/c/time/+/336469 merged a few days ago resolve this for you? |
Yes, it looks like it does. The unit test from the top post fails before that CL and passes with it. And your repo 3 comments up seems fine at head. (but it doesn't fail for me before @josharian's change either) |
Thanks. I didn't see it merged. |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
Write an unittest in rate_test.go and run
go test
func TestPreciseAllow(t *testing.T) {
lim := NewLimiter(0.00027777777777777778, 1)
lim.tokens = 0.54990492004805558
if !lim.Allow() {
t.Errorf("want ok, got false")
}
}
What did you expect to see?
Pass the unittest
What did you see instead?
Fail to pass the unittest
The text was updated successfully, but these errors were encountered: