Closed as duplicate of#47084
Description
What version of Go are you using (go version
)?
$ go version go version go1.13.7 linux/amd64
Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (go env
)?
go env
Output
$ go env GO111MODULE="" GOARCH="amd64" GOBIN="" GOCACHE="/home/alx/.cache/go-build" GOENV="/home/alx/.config/go/env" GOEXE="" GOFLAGS="" GOHOSTARCH="amd64" GOHOSTOS="linux" GONOPROXY="" GONOSUMDB="" GOOS="linux" GOPATH="/home/alx/go" GOPRIVATE="" GOPROXY="https://proxy.golang.org,direct" GOROOT="/usr/local/go" GOSUMDB="sum.golang.org" GOTMPDIR="" GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64" GCCGO="gccgo" AR="ar" CC="gcc" CXX="g++" CGO_ENABLED="1" GOMOD="" CGO_CFLAGS="-g -O2" CGO_CPPFLAGS="" CGO_CXXFLAGS="-g -O2" CGO_FFLAGS="-g -O2" CGO_LDFLAGS="-g -O2" PKG_CONFIG="pkg-config" GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build377469486=/tmp/go-build -gno-record-gcc-switches"
What 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.
package main
import (
"context"
"log"
"sync/atomic"
"time"
"golang.org/x/time/rate"
)
func main() {
var (
rps = 100000
duration = 10 * time.Second
)
requests := rps * int(duration.Seconds())
ctx, endCancel := context.WithTimeout(context.Background(), duration)
defer endCancel()
count := newCounter(ctx)
count.logState()
limiter := rate.NewLimiter(rate.Every(time.Second/time.Duration(rps)), 1)
for i := 0; i < requests; i++ {
count.inc()
err := limiter.Wait(ctx)
if err != nil {
log.Println("Limiter error", err)
break
}
}
}
type counter struct {
ctx context.Context
i int64
}
func newCounter(context context.Context) *counter {
return &counter{
ctx: context,
i: 0,
}
}
func (c *counter) inc() {
atomic.AddInt64(&c.i, 1)
}
func (c *counter) get() int64 {
return atomic.LoadInt64(&c.i)
}
func (c *counter) logState() {
go func() {
for {
select {
case <-c.ctx.Done():
return
default:
}
before := c.get()
time.Sleep(time.Second)
after := c.get()
log.Println(after - before)
}
}()
}
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?
2020/02/05 16:59:06 26208
2020/02/05 16:59:07 26139
2020/02/05 16:59:08 25750
2020/02/05 16:59:09 25942
2020/02/05 16:59:10 25252
2020/02/05 16:59:11 25847
2020/02/05 16:59:12 25949
2020/02/05 16:59:13 25353
2020/02/05 16:59:14 26985
2020/02/05 16:59:15 Limiter error rate: Wait(n=1) would exceed context deadline