diff options
| author | Mauri de Souza Meneguzzo <mauri870@gmail.com> | 2023-09-01 18:26:49 +0000 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2023-09-01 22:41:39 +0000 |
| commit | 7015ed891c6f4e51ebaa642fce42ea8a1592b4e1 (patch) | |
| tree | fa3841de5dffcbe813ff78069c476e6008fc08cd /src | |
| parent | 227ec028244b8ad91c7dd5b69fca5150f99a4878 (diff) | |
| download | go-7015ed891c6f4e51ebaa642fce42ea8a1592b4e1.tar.xz | |
sync: prevent (*Map).Range from always escaping
After the change from CL 426074 the Range method on Map always
escape the read variable, leading to an allocation.
Since the compiler doesn't do live-range splitting for local variables we
need to use some hints to only escape in that particular branch.
Fixes #62404
Change-Id: I938a5e593647455fa827e3dd3ed8ea22c7365df1
GitHub-Last-Rev: fcbedb467c7b4e6f1d49e299d243cad70deb34e9
GitHub-Pull-Request: golang/go#62408
Reviewed-on: https://go-review.googlesource.com/c/go/+/524976
Auto-Submit: Bryan Mills <bcmills@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Run-TryBot: Bryan Mills <bcmills@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Diffstat (limited to 'src')
| -rw-r--r-- | src/sync/map.go | 3 | ||||
| -rw-r--r-- | src/sync/map_test.go | 14 |
2 files changed, 16 insertions, 1 deletions
diff --git a/src/sync/map.go b/src/sync/map.go index e8ccf58b56..00b2446153 100644 --- a/src/sync/map.go +++ b/src/sync/map.go @@ -461,7 +461,8 @@ func (m *Map) Range(f func(key, value any) bool) { read = m.loadReadOnly() if read.amended { read = readOnly{m: m.dirty} - m.read.Store(&read) + copyRead := read + m.read.Store(©Read) m.dirty = nil m.misses = 0 } diff --git a/src/sync/map_test.go b/src/sync/map_test.go index 1eb3fc68a5..20872f3b72 100644 --- a/src/sync/map_test.go +++ b/src/sync/map_test.go @@ -5,6 +5,7 @@ package sync_test import ( + "internal/testenv" "math/rand" "reflect" "runtime" @@ -280,3 +281,16 @@ func TestCompareAndSwap_NonExistingKey(t *testing.T) { t.Fatalf("CompareAndSwap on an non-existing key succeeded") } } + +func TestMapRangeNoAllocations(t *testing.T) { // Issue 62404 + testenv.SkipIfOptimizationOff(t) + var m sync.Map + allocs := testing.AllocsPerRun(10, func() { + m.Range(func(key, value any) bool { + return true + }) + }) + if allocs > 0 { + t.Errorf("AllocsPerRun of m.Range = %v; want 0", allocs) + } +} |
