pool.go 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. package bytespool
  2. import "sync"
  3. func createAllocFunc(size int32) func() interface{} {
  4. return func() interface{} {
  5. return make([]byte, size)
  6. }
  7. }
  8. // The following parameters controls the size of buffer pools.
  9. // There are numPools pools. Starting from 2k size, the size of each pool is sizeMulti of the previous one.
  10. // Package buf is guaranteed to not use buffers larger than the largest pool.
  11. // Other packets may use larger buffers.
  12. const (
  13. numPools = 4
  14. sizeMulti = 4
  15. )
  16. var (
  17. pool [numPools]sync.Pool
  18. poolSize [numPools]int32
  19. )
  20. func init() {
  21. size := int32(2048)
  22. for i := 0; i < numPools; i++ {
  23. pool[i] = sync.Pool{
  24. New: createAllocFunc(size),
  25. }
  26. poolSize[i] = size
  27. size *= sizeMulti
  28. }
  29. }
  30. // Alloc returns a byte slice with at least the given size. Minimum size of returned slice is 2048.
  31. func Alloc(size int32) []byte {
  32. for idx, ps := range poolSize {
  33. if size <= ps {
  34. return pool[idx].Get().([]byte)
  35. }
  36. }
  37. return make([]byte, size)
  38. }
  39. // Free puts a byte slice into the internal pool.
  40. func Free(b []byte) {
  41. size := int32(cap(b))
  42. b = b[0:cap(b)]
  43. for i := numPools - 1; i >= 0; i-- {
  44. if size >= poolSize[i] {
  45. pool[i].Put(b) // nolint: megacheck
  46. return
  47. }
  48. }
  49. }