buffer_pool.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. package alloc
  2. import (
  3. "os"
  4. "strconv"
  5. "sync"
  6. )
  7. // Pool provides functionality to generate and recycle buffers on demand.
  8. type Pool interface {
  9. Allocate() *Buffer
  10. Free(*Buffer)
  11. }
  12. type SyncPool struct {
  13. allocator *sync.Pool
  14. }
  15. func NewSyncPool(bufferSize uint32) *SyncPool {
  16. pool := &SyncPool{
  17. allocator: &sync.Pool{
  18. New: func() interface{} { return make([]byte, bufferSize) },
  19. },
  20. }
  21. return pool
  22. }
  23. func (p *SyncPool) Allocate() *Buffer {
  24. return CreateBuffer(p.allocator.Get().([]byte), p)
  25. }
  26. func (p *SyncPool) Free(buffer *Buffer) {
  27. rawBuffer := buffer.head
  28. if rawBuffer == nil {
  29. return
  30. }
  31. p.allocator.Put(rawBuffer)
  32. }
  33. type BufferPool struct {
  34. chain chan []byte
  35. allocator *sync.Pool
  36. }
  37. func NewBufferPool(bufferSize, poolSize uint32) *BufferPool {
  38. pool := &BufferPool{
  39. chain: make(chan []byte, poolSize),
  40. allocator: &sync.Pool{
  41. New: func() interface{} { return make([]byte, bufferSize) },
  42. },
  43. }
  44. for i := uint32(0); i < poolSize; i++ {
  45. pool.chain <- make([]byte, bufferSize)
  46. }
  47. return pool
  48. }
  49. func (p *BufferPool) Allocate() *Buffer {
  50. var b []byte
  51. select {
  52. case b = <-p.chain:
  53. default:
  54. b = p.allocator.Get().([]byte)
  55. }
  56. return CreateBuffer(b, p)
  57. }
  58. func (p *BufferPool) Free(buffer *Buffer) {
  59. rawBuffer := buffer.head
  60. if rawBuffer == nil {
  61. return
  62. }
  63. select {
  64. case p.chain <- rawBuffer:
  65. default:
  66. p.allocator.Put(rawBuffer)
  67. }
  68. }
  69. const (
  70. mediumBufferByteSize = 8 * 1024
  71. BufferSize = mediumBufferByteSize - defaultOffset
  72. smallBufferByteSize = 2 * 1024
  73. SmallBufferSize = smallBufferByteSize - defaultOffset
  74. PoolSizeEnvKey = "v2ray.buffer.size"
  75. )
  76. var (
  77. mediumPool Pool
  78. smallPool = NewSyncPool(2048)
  79. )
  80. func init() {
  81. var size uint32 = 20
  82. sizeStr := os.Getenv(PoolSizeEnvKey)
  83. if len(sizeStr) > 0 {
  84. customSize, err := strconv.ParseUint(sizeStr, 10, 32)
  85. if err == nil {
  86. size = uint32(customSize)
  87. }
  88. }
  89. if size > 0 {
  90. totalByteSize := size * 1024 * 1024
  91. mediumPool = NewBufferPool(mediumBufferByteSize, totalByteSize/mediumBufferByteSize)
  92. } else {
  93. mediumPool = NewSyncPool(mediumBufferByteSize)
  94. }
  95. }