buffer.go 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. package alloc
  2. import (
  3. "time"
  4. )
  5. type Buffer struct {
  6. head []byte
  7. pool *bufferPool
  8. Value []byte
  9. }
  10. func (b *Buffer) Release() {
  11. b.pool.free(b)
  12. b.head = nil
  13. b.Value = nil
  14. b.pool = nil
  15. }
  16. func (b *Buffer) Clear() {
  17. b.Value = b.head[:0]
  18. }
  19. func (b *Buffer) Append(data []byte) {
  20. b.Value = append(b.Value, data...)
  21. }
  22. func (b *Buffer) Slice(from, to int) {
  23. b.Value = b.Value[from:to]
  24. }
  25. func (b *Buffer) SliceFrom(from int) {
  26. b.Value = b.Value[from:]
  27. }
  28. func (b *Buffer) Len() int {
  29. return len(b.Value)
  30. }
  31. type bufferPool struct {
  32. chain chan []byte
  33. bufferSize int
  34. buffers2Keep int
  35. }
  36. func newBufferPool(bufferSize, buffers2Keep, poolSize int) *bufferPool {
  37. pool := &bufferPool{
  38. chain: make(chan []byte, poolSize),
  39. bufferSize: bufferSize,
  40. buffers2Keep: buffers2Keep,
  41. }
  42. for i := 0; i < buffers2Keep; i++ {
  43. pool.chain <- make([]byte, bufferSize)
  44. }
  45. go pool.cleanup(time.Tick(1 * time.Second))
  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 = make([]byte, p.bufferSize)
  54. }
  55. return &Buffer{
  56. head: b,
  57. pool: p,
  58. Value: b,
  59. }
  60. }
  61. func (p *bufferPool) free(buffer *Buffer) {
  62. select {
  63. case p.chain <- buffer.head:
  64. default:
  65. }
  66. }
  67. func (p *bufferPool) cleanup(tick <-chan time.Time) {
  68. for range tick {
  69. pSize := len(p.chain)
  70. if pSize > p.buffers2Keep {
  71. <-p.chain
  72. continue
  73. }
  74. for delta := pSize - p.buffers2Keep; delta > 0; delta-- {
  75. p.chain <- make([]byte, p.bufferSize)
  76. }
  77. }
  78. }
  79. var smallPool = newBufferPool(8*1024, 256, 2048)
  80. func NewBuffer() *Buffer {
  81. return smallPool.allocate()
  82. }