buffer_pool.go 2.0 KB

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