pool.go 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  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. // GetPool returns a sync.Pool that generates bytes array with at least the given size.
  31. // It may return nil if no such pool exists.
  32. func GetPool(size int32) *sync.Pool {
  33. for idx, ps := range poolSize {
  34. if size <= ps {
  35. return &pool[idx]
  36. }
  37. }
  38. return nil
  39. }
  40. // Alloc returns a byte slice with at least the given size. Minimum size of returned slice is 2048.
  41. func Alloc(size int32) []byte {
  42. pool := GetPool(size)
  43. if pool != nil {
  44. return pool.Get().([]byte)
  45. }
  46. return make([]byte, size)
  47. }
  48. // Free puts a byte slice into the internal pool.
  49. func Free(b []byte) {
  50. size := int32(cap(b))
  51. b = b[0:cap(b)]
  52. for i := numPools - 1; i >= 0; i-- {
  53. if size >= poolSize[i] {
  54. pool[i].Put(b) // nolint: megacheck
  55. return
  56. }
  57. }
  58. }