Skip to content

Commit

Permalink
fix: mcache skip manage > 1gb buffer
Browse files Browse the repository at this point in the history
  • Loading branch information
joway committed Jun 3, 2024
1 parent 5df24c0 commit a37c8ca
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 8 deletions.
20 changes: 15 additions & 5 deletions lang/mcache/mcache.go
Original file line number Diff line number Diff line change
Expand Up @@ -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<<index
var caches [maxSize]sync.Pool
var caches [maxCachedIndex + 1]sync.Pool

func init() {
for i := 0; i < maxSize; i++ {
for i := 0; i <= maxCachedIndex; i++ {
size := 1 << i
caches[i].New = func() interface{} {
buf := dirtmake.Bytes(0, size)
Expand Down Expand Up @@ -57,15 +62,20 @@ func Malloc(size int, capacity ...int) []byte {
if len(capacity) > 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
}

// 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]
Expand Down
29 changes: 26 additions & 3 deletions lang/mcache/mcache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down

0 comments on commit a37c8ca

Please sign in to comment.