pool.go raw

   1  //go:build !(js && wasm)
   2  
   3  // Package bufpool provides buffer pools for reducing GC pressure in hot paths.
   4  //
   5  // Two pool sizes are provided:
   6  //   - SmallPool (64 bytes): For index keys, serial encoding, short buffers
   7  //   - MediumPool (1KB): For event encoding, larger serialization buffers
   8  //
   9  // Usage:
  10  //
  11  //	buf := bufpool.GetSmall()
  12  //	defer bufpool.PutSmall(buf)
  13  //	// Use buf...
  14  //	// IMPORTANT: Copy buf.Bytes() before Put if data is needed after
  15  package bufpool
  16  
  17  import (
  18  	"bytes"
  19  	"sync"
  20  )
  21  
  22  const (
  23  	// SmallBufferSize for index keys (8-64 bytes typical)
  24  	SmallBufferSize = 64
  25  
  26  	// MediumBufferSize for event encoding (300-1000 bytes typical)
  27  	MediumBufferSize = 1024
  28  )
  29  
  30  var (
  31  	// smallPool for index keys and short encodings
  32  	smallPool = sync.Pool{
  33  		New: func() interface{} {
  34  			return bytes.NewBuffer(make([]byte, 0, SmallBufferSize))
  35  		},
  36  	}
  37  
  38  	// mediumPool for event encoding and larger buffers
  39  	mediumPool = sync.Pool{
  40  		New: func() interface{} {
  41  			return bytes.NewBuffer(make([]byte, 0, MediumBufferSize))
  42  		},
  43  	}
  44  )
  45  
  46  // GetSmall returns a small buffer (64 bytes) from the pool.
  47  // Call PutSmall when done to return it to the pool.
  48  //
  49  // WARNING: Copy buf.Bytes() before calling PutSmall if the data
  50  // is needed after the buffer is returned to the pool.
  51  func GetSmall() *bytes.Buffer {
  52  	return smallPool.Get().(*bytes.Buffer)
  53  }
  54  
  55  // PutSmall returns a small buffer to the pool.
  56  // The buffer is reset before being returned.
  57  func PutSmall(buf *bytes.Buffer) {
  58  	if buf == nil {
  59  		return
  60  	}
  61  	buf.Reset()
  62  	smallPool.Put(buf)
  63  }
  64  
  65  // GetMedium returns a medium buffer (1KB) from the pool.
  66  // Call PutMedium when done to return it to the pool.
  67  //
  68  // WARNING: Copy buf.Bytes() before calling PutMedium if the data
  69  // is needed after the buffer is returned to the pool.
  70  func GetMedium() *bytes.Buffer {
  71  	return mediumPool.Get().(*bytes.Buffer)
  72  }
  73  
  74  // PutMedium returns a medium buffer to the pool.
  75  // The buffer is reset before being returned.
  76  func PutMedium(buf *bytes.Buffer) {
  77  	if buf == nil {
  78  		return
  79  	}
  80  	buf.Reset()
  81  	mediumPool.Put(buf)
  82  }
  83  
  84  // CopyBytes copies the buffer contents to a new slice.
  85  // Use this before returning the buffer to the pool if the
  86  // data needs to persist.
  87  func CopyBytes(buf *bytes.Buffer) []byte {
  88  	if buf == nil || buf.Len() == 0 {
  89  		return nil
  90  	}
  91  	result := make([]byte, buf.Len())
  92  	copy(result, buf.Bytes())
  93  	return result
  94  }
  95