From 3a19eea97c0456578eaef0bf31b136e5a7c3cb5e Mon Sep 17 00:00:00 2001 From: Chris Lu Date: Sat, 27 Nov 2021 12:13:00 -0800 Subject: [PATCH] allocate memory by slabs --- weed/util/mem/slot_pool.go | 44 +++++++++++++++++++++++++++++++++ weed/util/mem/slot_pool_test.go | 37 +++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 weed/util/mem/slot_pool.go create mode 100644 weed/util/mem/slot_pool_test.go diff --git a/weed/util/mem/slot_pool.go b/weed/util/mem/slot_pool.go new file mode 100644 index 000000000..e6680d3cb --- /dev/null +++ b/weed/util/mem/slot_pool.go @@ -0,0 +1,44 @@ +package mem + +import "sync" + +var pools []*sync.Pool + +const ( + min_size = 1024 +) + +func bitCount(size int) (count int) { + for ; size > min_size; count++ { + size = size >> 1 + } + return +} + +func init() { + // 1KB ~ 256MB + pools = make([]*sync.Pool, bitCount(1024*1024*256)) + for i := 0; i < len(pools); i++ { + slotSize := 1024 << i + pools[i] = &sync.Pool{ + New: func() interface{} { + buffer := make([]byte, slotSize) + return &buffer + }, + } + } +} + +func getSlotPool(size int) *sync.Pool { + index := bitCount(size) + return pools[index] +} + +func Allocate(size int) []byte { + slab := *getSlotPool(size).Get().(*[]byte) + return slab[:size] +} + +func Free(buf []byte) { + getSlotPool(cap(buf)).Put(&buf) +} diff --git a/weed/util/mem/slot_pool_test.go b/weed/util/mem/slot_pool_test.go new file mode 100644 index 000000000..114951522 --- /dev/null +++ b/weed/util/mem/slot_pool_test.go @@ -0,0 +1,37 @@ +package mem + +import ( + "testing" +) + +func TestAllocateFree(t *testing.T) { + buf := Allocate(12) + Free(buf) + if cap(buf) != min_size { + t.Errorf("min size error allocated capacity=%d", cap(buf)) + } + if len(buf) != 12 { + t.Errorf("size error") + } + + buf = Allocate(4883) + Free(buf) + if cap(buf) != 1024<