pool.go 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  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. //
  33. // xray:api:stable
  34. func GetPool(size int32) *sync.Pool {
  35. for idx, ps := range poolSize {
  36. if size <= ps {
  37. return &pool[idx]
  38. }
  39. }
  40. return nil
  41. }
  42. // Alloc returns a byte slice with at least the given size. Minimum size of returned slice is 2048.
  43. //
  44. // xray:api:stable
  45. func Alloc(size int32) []byte {
  46. pool := GetPool(size)
  47. if pool != nil {
  48. return pool.Get().([]byte)
  49. }
  50. return make([]byte, size)
  51. }
  52. // Free puts a byte slice into the internal pool.
  53. //
  54. // xray:api:stable
  55. func Free(b []byte) {
  56. size := int32(cap(b))
  57. b = b[0:cap(b)]
  58. for i := numPools - 1; i >= 0; i-- {
  59. if size >= poolSize[i] {
  60. pool[i].Put(b)
  61. return
  62. }
  63. }
  64. }