diff --git a/lang/mcache/mcache.go b/lang/mcache/mcache.go index 1e07472f..600427ac 100644 --- a/lang/mcache/mcache.go +++ b/lang/mcache/mcache.go @@ -20,13 +20,18 @@ import ( "github.com/bytedance/gopkg/lang/dirtmake" ) -const maxSize = 46 +const ( + maxCachedIndex = 30 // len(caches) = maxCachedIndex+1 + + // mcache will never cache the buffer that out of maxCachedSize, which will cause high memory usage + maxCachedSize = 1 << maxCachedIndex // 1GB +) // index contains []byte which cap is 1< 0 && capacity[0] > size { c = capacity[0] } - var ret = caches[calcIndex(c)].Get().([]byte) + if c > maxCachedSize { + return make([]byte, size, c) + } + + sizeIdx := calcIndex(c) + var ret = caches[sizeIdx].Get().([]byte) ret = ret[:size] return ret } @@ -65,7 +75,7 @@ func Malloc(size int, capacity ...int) []byte { // Free should be called when the buf is no longer used. func Free(buf []byte) { size := cap(buf) - if !isPowerOfTwo(size) { + if size > maxCachedSize || !isPowerOfTwo(size) { return } buf = buf[:0] diff --git a/lang/mcache/mcache_test.go b/lang/mcache/mcache_test.go index 1cfc9de4..964084a0 100644 --- a/lang/mcache/mcache_test.go +++ b/lang/mcache/mcache_test.go @@ -14,11 +14,34 @@ package mcache -import "testing" +import ( + "testing" + + "github.com/stretchr/testify/assert" +) func TestMalloc(t *testing.T) { - buf := Malloc(4096) - t.Log(cap(buf)) + // cached by mcache + size := 4096 - 1 + buf := Malloc(size) + assert.Equal(t, len(buf), size) + assert.Equal(t, cap(buf), size+1) + _ = buf[:size+1] // resize + Free(buf) + + // cached by mcache + size = 1024 * 1024 * 1024 + buf = Malloc(size) + assert.Equal(t, len(buf), size) + assert.Equal(t, cap(buf), size) + Free(buf) + + // not cached by mcache + size = 1024*1024*1024 + 1 + buf = Malloc(size) + assert.Equal(t, len(buf), size) + assert.Equal(t, cap(buf), size) + Free(buf) } func BenchmarkNormal4096(b *testing.B) {