Skip to content

Commit

Permalink
add cache manager
Browse files Browse the repository at this point in the history
  • Loading branch information
sunsc0220 committed Aug 2, 2022
1 parent 48f3d01 commit ea52ffb
Show file tree
Hide file tree
Showing 2 changed files with 166 additions and 0 deletions.
66 changes: 66 additions & 0 deletions cachem/cache.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package cachem

import (
"math/bits"
"sync"
)

const maxSize = 46

// index contains []byte which cap is 1<<index
var caches [maxSize]sync.Pool

func init() {
for i := 0; i < maxSize; i++ {
size := 1 << i
caches[i].New = func() interface{} {
buf := make([]byte, 0, size)
return buf
}
}
}

// calculates which pool to get from
func calcIndex(size int) int {
if size == 0 {
return 0
}
if isPowerOfTwo(size) {
return bsr(size)
}
return bsr(size) + 1
}

// Malloc supports one or two integer argument.
// The size specifies the length of the returned slice, which means len(ret) == size.
// A second integer argument may be provided to specify the minimum capacity, which means cap(ret) >= cap.
func Malloc(size int, capacity ...int) []byte {
if len(capacity) > 1 {
panic("too many arguments to Malloc")
}
var c = size
if len(capacity) > 0 && capacity[0] > size {
c = capacity[0]
}
var ret = caches[calcIndex(c)].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) {
return
}
buf = buf[:0]
caches[bsr(size)].Put(buf)
}

func bsr(x int) int {
return bits.Len(uint(x)) - 1
}

func isPowerOfTwo(x int) bool {
return (x & (-x)) == x
}
100 changes: 100 additions & 0 deletions cachem/cache_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package cachem

import "testing"

func TestMalloc(t *testing.T) {
buf := Malloc(4096)
t.Log(cap(buf))
}

func BenchmarkNormal4096(b *testing.B) {
var buf []byte
b.ReportAllocs()
for i := 0; i < b.N; i++ {
buf = make([]byte, 0, 4096)
}
_ = buf
}

func BenchmarkMCache4096(b *testing.B) {
var buf []byte
b.ReportAllocs()
for i := 0; i < b.N; i++ {
buf = Malloc(4096)
Free(buf)
}
_ = buf
}

func BenchmarkNormal10M(b *testing.B) {
var buf []byte
b.ReportAllocs()
for i := 0; i < b.N; i++ {
buf = make([]byte, 0, 1024*1024*10)
}
_ = buf
}

func BenchmarkMCache10M(b *testing.B) {
var buf []byte
b.ReportAllocs()
for i := 0; i < b.N; i++ {
buf = Malloc(1024 * 1024 * 10)
Free(buf)
}
_ = buf
}

func BenchmarkNormal4096Parallel(b *testing.B) {
b.ReportAllocs()
b.RunParallel(func(pb *testing.PB) {
var buf []byte
for pb.Next() {
for i := 0; i < b.N; i++ {
buf = make([]byte, 0, 4096)
}
}
_ = buf
})
}

func BenchmarkMCache4096Parallel(b *testing.B) {
b.ReportAllocs()
b.RunParallel(func(pb *testing.PB) {
var buf []byte
for pb.Next() {
for i := 0; i < b.N; i++ {
buf = Malloc(4096)
Free(buf)
}
}
_ = buf
})
}

func BenchmarkNormal10MParallel(b *testing.B) {
b.ReportAllocs()
b.RunParallel(func(pb *testing.PB) {
var buf []byte
for pb.Next() {
for i := 0; i < b.N; i++ {
buf = make([]byte, 0, 1024*1024*10)
}
}
_ = buf
})
}

func BenchmarkMCache10MParallel(b *testing.B) {
b.ReportAllocs()
b.RunParallel(func(pb *testing.PB) {
var buf []byte
for pb.Next() {
for i := 0; i < b.N; i++ {
buf = Malloc(1024 * 1024 * 10)
Free(buf)
}
}
_ = buf
})
}

0 comments on commit ea52ffb

Please sign in to comment.