From d18167fefea5e77388dbc1e323e8527b58494185 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Mon, 26 Oct 2015 12:38:47 -0700 Subject: [PATCH] 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 TryBot-Result: Gobot Gobot Reviewed-by: Ian Lance Taylor --- src/runtime/malloc.go | 2 +- src/runtime/malloc_test.go | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go index 564e2296a2a..ae28a3c3190 100644 --- a/src/runtime/malloc.go +++ b/src/runtime/malloc.go @@ -615,7 +615,7 @@ func mallocgc(size uintptr, typ *_type, flags uint32) unsafe.Pointer { (*[2]uint64)(x)[1] = 0 // See if we need to replace the existing tiny block with the new one // based on amount of remaining free space. - if size < c.tinyoffset { + if size < c.tinyoffset || c.tiny == nil { c.tiny = x c.tinyoffset = size } diff --git a/src/runtime/malloc_test.go b/src/runtime/malloc_test.go index f0e73baea59..b8278bb4bca 100644 --- a/src/runtime/malloc_test.go +++ b/src/runtime/malloc_test.go @@ -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 func BenchmarkMalloc8(b *testing.B) {