golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
123.62k stars 17.61k forks source link

x/time/rate: reservation's delay is longer than expected if the previous one is not ok #52584

Closed cncal closed 1 year ago

cncal commented 2 years ago

What version of Go are you using (go version)?

$ go version
go version go1.17 darwin/amd64

Does this issue reproduce with the latest release?

Yes, it reproduces with go1.18.

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE="on"
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/cn/Library/Caches/go-build"
GOENV="/Users/cn/Library/Application Support/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/cn/Workspace/golang/pkg/mod"
GOOS="darwin"
GOPATH="/Users/cn/Workspace/golang"
GOPRIVATE=""
GOPROXY="https://goproxy.cn,direct"
GOROOT="/Users/cn/Workspace/gosdk/go1.17"
GOSUMDB="sum.golang.google.cn"
GOTMPDIR=""
GOTOOLDIR="/Users/cn/Workspace/gosdk/go1.17/pkg/tool/darwin_amd64"
GOVCS=""
GOVERSION="go1.17"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -arch x86_64 -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/9d/p9d0dmmj04zfrll8cm7rndsm0000gn/T/go-build2220765180=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

https://go.dev/play/p/vGnnjsqOcTp?v=goprev.

What did you expect to see?

I expect r.Delay() returns 200ms, just like https://go.dev/play/p/knb4-IPMUFd?v=goprev.

What did you see instead?

r.Delay() returns 300ms. Both of previous reservations are not ok, why the later reservation returns different delay.

cagedmantis commented 2 years ago

/cc @bcmills @Sajmani

gopherbot commented 2 years ago

Change https://go.dev/cl/406154 mentions this issue: rate: the state of the limiter should not be changed when the requests failed

ZekeLu commented 2 years ago

I think the correct value is 300ms.

See https://go.dev/play/p/X_jeZbv_mRy?v=goprev which removes the line lim.ReserveN(t0, 3) that causes the error.

Note that the burst is 2 so that at t1 before the request (lim.ReserveN(t1, 2).OK()), there are 2 tokens in the bucket (instead of 3).

Regarding the error caused by lim.ReserveN(t0, 3), I have sent a CL to fix it.