You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

sizedbufferpool.go 1.9KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. package render
  2. import (
  3. "bytes"
  4. )
  5. // Pulled from the github.com/oxtoacart/bpool package (Apache licensed).
  6. // SizedBufferPool implements a pool of bytes.Buffers in the form of a bounded
  7. // channel. Buffers are pre-allocated to the requested size.
  8. type SizedBufferPool struct {
  9. c chan *bytes.Buffer
  10. a int
  11. }
  12. // NewSizedBufferPool creates a new BufferPool bounded to the given size.
  13. // size defines the number of buffers to be retained in the pool and alloc sets
  14. // the initial capacity of new buffers to minimize calls to make().
  15. //
  16. // The value of alloc should seek to provide a buffer that is representative of
  17. // most data written to the the buffer (i.e. 95th percentile) without being
  18. // overly large (which will increase static memory consumption). You may wish to
  19. // track the capacity of your last N buffers (i.e. using an []int) prior to
  20. // returning them to the pool as input into calculating a suitable alloc value.
  21. func NewSizedBufferPool(size int, alloc int) (bp *SizedBufferPool) {
  22. return &SizedBufferPool{
  23. c: make(chan *bytes.Buffer, size),
  24. a: alloc,
  25. }
  26. }
  27. // Get gets a Buffer from the SizedBufferPool, or creates a new one if none are
  28. // available in the pool. Buffers have a pre-allocated capacity.
  29. func (bp *SizedBufferPool) Get() (b *bytes.Buffer) {
  30. select {
  31. case b = <-bp.c:
  32. // reuse existing buffer
  33. default:
  34. // create new buffer
  35. b = bytes.NewBuffer(make([]byte, 0, bp.a))
  36. }
  37. return
  38. }
  39. // Put returns the given Buffer to the SizedBufferPool.
  40. func (bp *SizedBufferPool) Put(b *bytes.Buffer) {
  41. b.Reset()
  42. // Release buffers over our maximum capacity and re-create a pre-sized
  43. // buffer to replace it.
  44. // Note that the cap(b.Bytes()) provides the capacity from the read off-set
  45. // only, but as we've called b.Reset() the full capacity of the underlying
  46. // byte slice is returned.
  47. if cap(b.Bytes()) > bp.a {
  48. b = bytes.NewBuffer(make([]byte, 0, bp.a))
  49. }
  50. select {
  51. case bp.c <- b:
  52. default: // Discard the buffer if the pool is full.
  53. }
  54. }