github.com/ulule/limiter/v3@v3.11.3-0.20230613131926-4cb9c1da4633/internal/bytebuffer/pool.go (about)

     1  package bytebuffer
     2  
     3  import (
     4  	"sync"
     5  	"unsafe"
     6  )
     7  
     8  // ByteBuffer is a wrapper around a slice to reduce memory allocation while handling blob of data.
     9  type ByteBuffer struct {
    10  	blob []byte
    11  }
    12  
    13  // New creates a new ByteBuffer instance.
    14  func New() *ByteBuffer {
    15  	entry := bufferPool.Get().(*ByteBuffer)
    16  	entry.blob = entry.blob[:0]
    17  	return entry
    18  }
    19  
    20  // Bytes returns the content buffer.
    21  func (buffer *ByteBuffer) Bytes() []byte {
    22  	return buffer.blob
    23  }
    24  
    25  // String returns the content buffer.
    26  func (buffer *ByteBuffer) String() string {
    27  	// Copied from strings.(*Builder).String
    28  	return *(*string)(unsafe.Pointer(&buffer.blob)) // nolint: gosec
    29  }
    30  
    31  // Concat appends given arguments to blob content
    32  func (buffer *ByteBuffer) Concat(args ...string) {
    33  	for i := range args {
    34  		buffer.blob = append(buffer.blob, args[i]...)
    35  	}
    36  }
    37  
    38  // Close recycles underlying resources of encoder.
    39  func (buffer *ByteBuffer) Close() {
    40  	// Proper usage of a sync.Pool requires each entry to have approximately
    41  	// the same memory cost. To obtain this property when the stored type
    42  	// contains a variably-sized buffer, we add a hard limit on the maximum buffer
    43  	// to place back in the pool.
    44  	//
    45  	// See https://golang.org/issue/23199
    46  	if buffer != nil && cap(buffer.blob) < (1<<16) {
    47  		bufferPool.Put(buffer)
    48  	}
    49  }
    50  
    51  // A byte buffer pool to reduce memory allocation pressure.
    52  var bufferPool = &sync.Pool{
    53  	New: func() interface{} {
    54  		return &ByteBuffer{
    55  			blob: make([]byte, 0, 1024),
    56  		}
    57  	},
    58  }