Skip to content
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

runtime: map's loadFactor is actually 6, not 6.5 #63438

xiangxu126 opened this issue Oct 7, 2023 · 10 comments

runtime: map's loadFactor is actually 6, not 6.5 #63438

xiangxu126 opened this issue Oct 7, 2023 · 10 comments


Copy link

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

$ go version
go version go1.21rc3 windows/amd64

Does this issue reproduce with the latest release?


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

go env Output
$ go env
set GO111MODULE=on
set GOARCH=amd64
set GOBIN=
set GOCACHE=C:\Users\xiangxu\AppData\Local\go-build
set GOENV=C:\Users\xiangxu\AppData\Roaming\go\env
set GOEXE=.exe
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOMODCACHE=C:\Users\xiangxu\go\pkg\mod
set GOOS=windows
set GOPATH=C:\Users\xiangxu\go
set GOPROXY=,direct
set GOROOT=C:/Users/xiangxu/sdk/go1.21rc3
set GOTOOLDIR=C:\Users\xiangxu\sdk\go1.21rc3\pkg\tool\windows_amd64
set GOVCS=
set GOVERSION=go1.21rc3
set GCCGO=gccgo
set GOAMD64=v1
set AR=ar
set CC=gcc
set CXX=g++
set GOMOD=C:\Users\xiangxu\GolandProjects\fastSlice\go.mod
set CGO_CFLAGS=-O2 -g
set CGO_FFLAGS=-O2 -g
set CGO_LDFLAGS=-O2 -g
set PKG_CONFIG=pkg-config
set GOGCCFLAGS=-m64 -fno-caret-diagnostics -Qunused-arguments -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=C:\Users\xiangxu\AppData\Local\Te
mp\go-build3346316506=/tmp/go-build -gno-record-gcc-switches

What did you do?

I found that due to integer arithmetic , loadFactorNum was incorrectly calculated as 12, resulting map triggers growth when
count > 6*(1<<B) , instead of the expected count > 6.5*(1<<B) .
The code related to the bug I mentioned can be found: code
You can verify this point easily with the following code:

package bench

import "testing"

var m map[int]int

func Benchmark1(b *testing.B) {
	for i := 0; i < b.N; i++ {
		m = make(map[int]int, 6*(1<<10))
func Benchmark2(b *testing.B) {
	for i := 0; i < b.N; i++ {
		m = make(map[int]int, 6*(1<<10)+1)

What did you expect to see?

The results of these two benchmark tests should be close.

What did you see instead?

In fact, this first benchmark test only takes half the time each time compared to the second benchmark test. It indicates that map triggers growth, but at this time, count < 6.5*(1<<B) still holds true.

goos: windows
goarch: amd64
pkg: fastSlice/bench
cpu: AMD Ryzen 9 7940HS w/ Radeon 780M Graphics
Benchmark1-16              95134             12748 ns/op
Benchmark2-16              45301             26307 ns/op
@xiangxu126 xiangxu126 changed the title runtime: loadFactor of map is 6 instead of 6.5 Runtime: map's loadFactor is actually 6, not 6.5 Oct 7, 2023
Copy link

This looks like it was broken in CL 462115. @dr2chase

Copy link

Change mentions this issue: map: use correct load factor for deciding when to grow

@seankhliao seankhliao changed the title Runtime: map's loadFactor is actually 6, not 6.5 runtime: map's loadFactor is actually 6, not 6.5 Oct 8, 2023
yunginnanet pushed a commit to yunginnanet/go that referenced this issue Oct 20, 2023
The correct load factor is 6.5, not 6.
This got broken by accident in CL 462115.

Fixes golang#63438

Change-Id: Ib07bb6ab6103aec87cb775bc06bd04362a64e489
Reviewed-by: David Chase <>
Reviewed-by: Keith Randall <>
Reviewed-by: Cuong Manh Le <>
LUCI-TryBot-Result: Go LUCI <>
Copy link

@gopherbot I believe this should be cherry-pick to 1.21.

Copy link

I don't think this qualifies for a backport. It would need to be a serious problem with no workaround. A minor performance difference does not qualify.

Copy link

It's not just a minor performance issue, it basically changes the way how a map grows.

As the issue mentions, the load factor becomes 6 rather than 6.5 anymore. I already test on 1.20 and 1.22 beta and find that their load factor of map is 6.5 not 6. If we do not cherry-pick this fix to 1.21, only 1.21 becomes an outlier.

If any program tracks the memory usage depends on one assumption: the load factor of map in golang is 6.5 not 6. It causes a lot of troubles.

Copy link

Sorry, we've made the call that it just isn't worth the risk to backport fixes like this.

Copy link

Can I know more details behind the scenes? To me, I could not see any risk, maybe you can help me to understand a little deeper. The load factor number of map in golang is always 6.5, I just could not understand changing back from 6 to 6.5 causses any potential risk.

Copy link

It's not anything about the particular CL or how safe it is (although if a CL is particularly risky, we get even more cautious). We just have a policy that we don't backport anything that isn't for a serious problem.
"Serious problems" do not include performance changes that otherwise adhere to the spec. Map growth thresholds are not any kind of spec-level guarantee.

Copy link

It's nice to know how the decision was made. Thanks for your time, I really appreciate this. @randall77

Copy link

appreciate the decision to not backport this btw - it seems like it somehow caused a regression (which is quite bizarre) #65706

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
None yet
None yet

No branches or pull requests

5 participants