buffer_pool.go 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  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 BufferPool struct {
  12. chain chan []byte
  13. allocator *sync.Pool
  14. }
  15. func NewBufferPool(bufferSize, poolSize uint32) *BufferPool {
  16. pool := &BufferPool{
  17. chain: make(chan []byte, poolSize),
  18. allocator: &sync.Pool{
  19. New: func() interface{} { return make([]byte, bufferSize) },
  20. },
  21. }
  22. for i := uint32(0); i < poolSize; i++ {
  23. pool.chain <- make([]byte, bufferSize)
  24. }
  25. return pool
  26. }
  27. func (p *BufferPool) Allocate() *Buffer {
  28. var b []byte
  29. select {
  30. case b = <-p.chain:
  31. default:
  32. b = p.allocator.Get().([]byte)
  33. }
  34. return CreateBuffer(b, p)
  35. }
  36. func (p *BufferPool) Free(buffer *Buffer) {
  37. rawBuffer := buffer.head
  38. if rawBuffer == nil {
  39. return
  40. }
  41. select {
  42. case p.chain <- rawBuffer:
  43. default:
  44. p.allocator.Put(rawBuffer)
  45. }
  46. }
  47. const (
  48. mediumBufferByteSize = 8 * 1024
  49. BufferSize = mediumBufferByteSize - defaultOffset
  50. largeBufferByteSize = 64 * 1024
  51. LargeBufferSize = largeBufferByteSize - defaultOffset
  52. PoolSizeEnvKey = "v2ray.buffer.size"
  53. )
  54. var (
  55. mediumPool *BufferPool
  56. )
  57. func init() {
  58. var size uint32 = 20
  59. sizeStr := os.Getenv(PoolSizeEnvKey)
  60. if len(sizeStr) > 0 {
  61. customSize, err := strconv.ParseUint(sizeStr, 10, 32)
  62. if err == nil {
  63. size = uint32(customSize)
  64. }
  65. }
  66. totalByteSize := size * 1024 * 1024
  67. mediumPool = NewBufferPool(mediumBufferByteSize, totalByteSize/mediumBufferByteSize)
  68. }