-
Notifications
You must be signed in to change notification settings - Fork 17.5k
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: Limiter.Wait waits too long #47084
Comments
Have you been able to determine whether this is due to a change in the |
hey @mknyszek I was able to use bisect and pin it down to: 8fdc79e
|
@ChrisHines @prattmic Is this the same root cause as #44343? |
It is, but we've been having other late timer issues since 8fdc79e and I thought that issue spun out of that. Perhaps its moved on from the general issues around that commit. |
This is probably the same cause as #44343. That bug is mostly discussing Windows as the problem is more pronounced there (15ms sleeps), but it does exist on Linux as well (1ms sleeps). |
I agree that the change in behavior goes back to 8fdc79e. After that change timers rely entirely on the netpoller to sleep and wakeup threads. It removed a variable frequency polling loop in the On linux that polling loop could run as frequently as every ~20 microseconds or as infrequently as every 10 milliseconds. By comparison the netpoller on linux has a wakeup granularity of ~1 millisecond. So that change reduced the worst case sleep time from 10ms to 1ms on linux, but also raised the best case time. As a counter point, the change also helped reduce CPU load for programs that mostly do lots of sleeps (see: #27707 (comment)). The test code above calls As a result the test is performing the equivalent of ~150,000 sleeps of 1ms, which matches up reasonably well with the report of the total runtime of 160 seconds. The above test wants to allow 300,000 events in 10 seconds which is the same as 30 events per ms. If we know that the Go 1.16 runtime cannot reliably perform sleeps less than 1ms, then using a burst size ~30 would be more achievable. That should allow 30 events back-to-back followed by a ~1ms sleep and another 30 events, etc. |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
yes, tested on 1.17beta1 as well.
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
I created a reproduction case: https://github.com/beanieboi/go-rate-limiter-bug/blob/main/main_test.go
in short. we are using the time
rate.NewLimiter()
withlimiter.Wait(ctx)
and see much longer wait times than on 1.15.7What did you expect to see?
the same behaviour as on 1.15.7, the tests linked above should finish within ~15s
What did you see instead?
the limiter is waiting too long and the whole test takes ~160s instead of ~15s
The text was updated successfully, but these errors were encountered: