diff options
author | Michael Anthony Knyszek <mknyszek@google.com> | 2020-09-16 16:22:28 +0000 |
---|---|---|
committer | Michael Knyszek <mknyszek@google.com> | 2020-09-16 17:07:38 +0000 |
commit | 2ae2a94857cb17a98a86a8332d6f76863982bf59 (patch) | |
tree | d9cc778fe5ef08e0b20391d52fce199e4d674b80 /src/runtime/export_test.go | |
parent | 37aa65357007411d121fbdbaa5a340aba21ab40a (diff) | |
download | go-2ae2a94857cb17a98a86a8332d6f76863982bf59.tar.gz go-2ae2a94857cb17a98a86a8332d6f76863982bf59.zip |
runtime: fix leak and locking in BenchmarkMSpanCountAlloc
CL 249917 made the mspan in MSpanCountAlloc no longer stack-allocated
(for good reason), but then allocated an mspan on each call and did not
free it, resulting in a leak. That allocation was also not protected by
the heap lock, which could lead to data corruption of mheap fields and
the spanalloc.
To fix this, export some functions to allocate/free dummy mspans from
spanalloc (with proper locking) and allocate just one up-front for the
benchmark, freeing it at the end. Then, update MSpanCountAlloc to accept
a dummy mspan.
Note that we need to allocate the dummy mspan up-front otherwise we
measure things like heap locking and fixalloc performance instead of
what we actually want to measure: how fast we can do a popcount on the
mark bits.
Fixes #41391.
Change-Id: If6629a6ec1ece639c7fb78532045837a8c872c04
Reviewed-on: https://go-review.googlesource.com/c/go/+/255297
Run-TryBot: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Michael Knyszek <mknyszek@google.com>
Diffstat (limited to 'src/runtime/export_test.go')
-rw-r--r-- | src/runtime/export_test.go | 28 |
1 files changed, 25 insertions, 3 deletions
diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go index 929bb35db6..e3d6441c18 100644 --- a/src/runtime/export_test.go +++ b/src/runtime/export_test.go @@ -983,9 +983,31 @@ func MapHashCheck(m interface{}, k interface{}) (uintptr, uintptr) { return x, y } -func MSpanCountAlloc(bits []byte) int { - s := (*mspan)(mheap_.spanalloc.alloc()) +// mspan wrapper for testing. +//go:notinheap +type MSpan mspan + +// Allocate an mspan for testing. +func AllocMSpan() *MSpan { + var s *mspan + systemstack(func() { + s = (*mspan)(mheap_.spanalloc.alloc()) + }) + return (*MSpan)(s) +} + +// Free an allocated mspan. +func FreeMSpan(s *MSpan) { + systemstack(func() { + mheap_.spanalloc.free(unsafe.Pointer(s)) + }) +} + +func MSpanCountAlloc(ms *MSpan, bits []byte) int { + s := (*mspan)(ms) s.nelems = uintptr(len(bits) * 8) s.gcmarkBits = (*gcBits)(unsafe.Pointer(&bits[0])) - return s.countAlloc() + result := s.countAlloc() + s.gcmarkBits = nil + return result } |