1
0
mirror of https://github.com/golang/go synced 2024-11-23 19:30:05 -07:00

runtime: fix tiny allocator

When a new tiny block is allocated because we're allocating an object
that won't fit into the current block, mallocgc saves the new block if
it has more space leftover than the old block.  However, the logic for
this was subtly broken in golang.org/cl/2814, resulting in never
saving (or consequently reusing) a tiny block.

Change-Id: Ib5f6769451fb82877ddeefe75dfe79ed4a04fd40
Reviewed-on: https://go-review.googlesource.com/16330
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
Matthew Dempsky 2015-10-26 12:38:47 -07:00
parent e6ccfc1ad1
commit d18167fefe
2 changed files with 18 additions and 1 deletions

View File

@ -615,7 +615,7 @@ func mallocgc(size uintptr, typ *_type, flags uint32) unsafe.Pointer {
(*[2]uint64)(x)[1] = 0 (*[2]uint64)(x)[1] = 0
// See if we need to replace the existing tiny block with the new one // See if we need to replace the existing tiny block with the new one
// based on amount of remaining free space. // based on amount of remaining free space.
if size < c.tinyoffset { if size < c.tinyoffset || c.tiny == nil {
c.tiny = x c.tiny = x
c.tinyoffset = size c.tinyoffset = size
} }

View File

@ -82,6 +82,23 @@ func TestStringConcatenationAllocs(t *testing.T) {
} }
} }
func TestTinyAlloc(t *testing.T) {
const N = 16
var v [N]unsafe.Pointer
for i := range v {
v[i] = unsafe.Pointer(new(byte))
}
chunks := make(map[uintptr]bool, N)
for _, p := range v {
chunks[uintptr(p)&^7] = true
}
if len(chunks) == N {
t.Fatal("no bytes allocated within the same 8-byte chunk")
}
}
var mallocSink uintptr var mallocSink uintptr
func BenchmarkMalloc8(b *testing.B) { func BenchmarkMalloc8(b *testing.B) {