github.com/sunvim/utils@v0.1.0/cachem/cache.go (about)

     1  package cachem
     2  
     3  import (
     4  	"math/bits"
     5  	"sync"
     6  )
     7  
     8  const maxSize = 46
     9  
    10  // index contains []byte which cap is 1<<index
    11  var caches [maxSize]sync.Pool
    12  
    13  func init() {
    14  	for i := 0; i < maxSize; i++ {
    15  		size := 1 << i
    16  		caches[i].New = func() interface{} {
    17  			buf := make([]byte, 0, size)
    18  			return buf
    19  		}
    20  	}
    21  }
    22  
    23  // calculates which pool to get from
    24  func calcIndex(size int) int {
    25  	if size == 0 {
    26  		return 0
    27  	}
    28  	if isPowerOfTwo(size) {
    29  		return bsr(size)
    30  	}
    31  	return bsr(size) + 1
    32  }
    33  
    34  // Malloc supports one or two integer argument.
    35  // The size specifies the length of the returned slice, which means len(ret) == size.
    36  // A second integer argument may be provided to specify the minimum capacity, which means cap(ret) >= cap.
    37  func Malloc(size int, capacity ...int) []byte {
    38  	if len(capacity) > 1 {
    39  		panic("too many arguments to Malloc")
    40  	}
    41  	var c = size
    42  	if len(capacity) > 0 && capacity[0] > size {
    43  		c = capacity[0]
    44  	}
    45  	var ret = caches[calcIndex(c)].Get().([]byte)
    46  	ret = ret[:size]
    47  	return ret
    48  }
    49  
    50  // Free should be called when the buf is no longer used.
    51  func Free(buf []byte) {
    52  	size := cap(buf)
    53  	if !isPowerOfTwo(size) {
    54  		return
    55  	}
    56  	buf = buf[:0]
    57  	caches[bsr(size)].Put(buf)
    58  }
    59  
    60  func bsr(x int) int {
    61  	return bits.Len(uint(x)) - 1
    62  }
    63  
    64  func isPowerOfTwo(x int) bool {
    65  	return (x & (-x)) == x
    66  }