Open lebovski opened 4 years ago
I can reproduce on Linux. Both 1.13.7 and tip.
I can not reproduce on Darwin - that can do ~96K/sec.
Increasing the burst size fixes this on Linux. Using 10 instead of 1 fixes the problem. At a rate of 100K/sec, you should probably allow bursts >1.
Not sure what the underlying problem is. Timer quantization, perhaps?
limiter.Wait(ctx) will call time.NewTimer() if need to wait. I make a test for time.NewTimer(d) using similar parameters with @lebovski. And I find total call time.NewTimer(d) does not correspond to expected. And I find the smaller the duration d , the greater the deviation.
env: go version go1.14 linux/amd64
// test code
package main
import (
"context"
"fmt"
"time"
)
func testTimer(d time.Duration, ctx context.Context) (count int) {
for {
t := time.NewTimer(d)
select {
case <-ctx.Done():
return
case <-t.C:
count++
}
}
return
}
func main() {
d := 10 * time.Microsecond
timeout := 10 * time.Second
ctx, _ := context.WithTimeout(context.Background(), timeout)
fmt.Printf("want %d, got %d.\n", int64(timeout/d), testTimer(d, ctx))
}
// output:
// want 1000000, got 60830.
As @randall77 said: increasing the burst size can fixes the problem. That's because increasing the burst size will reduce to call time.NewTimer().
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?
I use rate limiter from standard library in order to limit the number of cycles of a some operation. The actual RPS is printed every second.
What did you expect to see?
Expected that the actual RPS would be about 100000, but in fact it's only about 26000. Also the CPU is underloaded (CPU usage is around 60-70% on my hardware, so it doesn't even consume a single core).
What did you see instead?