github.com/sandwich-go/boost@v1.3.29/xpool/buffer.go (about) 1 package xpool 2 3 import ( 4 "fmt" 5 "sync" 6 ) 7 8 // BytesPool bytes pool 9 type BytesPool interface { 10 // Alloc try alloc a []byte from internal slab class if no free chunk in slab class Alloc will make one. 11 Alloc(size int) []byte 12 // Free release a []byte that alloc from BytesPool.Alloc. 13 Free(mem []byte) 14 } 15 16 var debug bool 17 18 // SyncBytesPool is a sync.Pool base slab allocation memory pool 19 type SyncBytesPool struct { 20 chunks []sync.Pool 21 sizes []int 22 minSize int 23 maxSize int 24 25 // for testing 26 allocTimesFromPool int 27 freeTimesToPool int 28 } 29 30 // NewSyncBytesPool create a sync.Pool base slab allocation memory pool. 31 // minSize is the smallest chunk size. 32 // maxSize is the largest chunk size. 33 // factor is used to control growth of chunk size. 34 func NewSyncBytesPool(minSize, maxSize, factor int) BytesPool { 35 n := 0 36 if minSize <= 0 || factor <= 0 { 37 panic(fmt.Sprintf("invalid paramter, minSize/factor should greater than 0")) 38 } 39 for chunkSize := minSize; chunkSize <= maxSize; chunkSize *= factor { 40 n++ 41 } 42 pool := &SyncBytesPool{ 43 chunks: make([]sync.Pool, n), 44 sizes: make([]int, n), 45 minSize: minSize, maxSize: maxSize, 46 } 47 n = 0 48 for chunkSize := minSize; chunkSize <= maxSize; chunkSize *= factor { 49 pool.sizes[n] = chunkSize 50 pool.chunks[n].New = func(size int) func() interface{} { 51 return func() interface{} { 52 buf := make([]byte, size) 53 return &buf 54 } 55 }(chunkSize) 56 n++ 57 } 58 return pool 59 } 60 61 // Alloc try alloc a []byte from internal slab class if no free chunk in slab class Alloc will make one. 62 func (p *SyncBytesPool) Alloc(size int) []byte { 63 if size <= p.maxSize { 64 for i := 0; i < len(p.sizes); i++ { 65 if p.sizes[i] >= size { 66 mem := p.chunks[i].Get().(*[]byte) 67 if debug { 68 p.allocTimesFromPool++ 69 } 70 return (*mem)[:size] 71 } 72 } 73 } 74 return make([]byte, size) 75 } 76 77 // Free release a []byte that alloc from SyncBytesPool.Alloc. 78 func (p *SyncBytesPool) Free(mem []byte) { 79 if size := cap(mem); size <= p.maxSize { 80 for i := 0; i < len(p.sizes); i++ { 81 if p.sizes[i] == size { 82 p.chunks[i].Put(&mem) 83 if debug { 84 p.freeTimesToPool++ 85 } 86 return 87 } else if p.sizes[i] > size && i > 0 && p.sizes[i-1] <= size { 88 p.chunks[i-1].Put(&mem) 89 if debug { 90 p.freeTimesToPool++ 91 } 92 return 93 } 94 } 95 } 96 }