pool

package
v1.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 30, 2026 License: MIT Imports: 2 Imported by: 0

Documentation

Overview

Package pool provides a sync.Pool-based buffer pool with size-class bucketing for zero-allocation serialization workflows. It is designed to eliminate GC pressure in request-response hot paths by reusing byte buffers across repeated marshal operations.

Buffers are organized into size classes based on powers of 2, starting at 64 bytes and extending up to a configurable maximum pooled size (1 MiB). Each size class maintains its own sync.Pool instance, and the appropriate class is selected in O(1) using math/bits.Len. Buffers exceeding the maximum pooled size are allocated directly and silently discarded on Put rather than being returned to the pool.

Get returns a []byte with len == 0 and cap >= the requested minimum capacity, rounded up to the next power-of-2 size class. On a pool hit the call performs zero heap allocations. Put returns a buffer to the appropriate size-class pool; it silently discards buffers that exceed the maximum pooled size or have zero capacity.

The package defines three interfaces for zero-allocation marshaling: MarshalAppend for append-style serialization, Sizer for deterministic size pre-computation, and Marshaler which embeds both. The Marshal convenience function combines Size, Get, and MarshalAppend into a single call that returns a pool-sourced buffer containing serialized data.

This package has zero external dependencies; it uses only sync and math/bits from the standard library.

Index

Constants

This section is empty.

Variables

View Source
var DefaultPool = NewPool()

DefaultPool is the package-level pool instance, analogous to http.DefaultClient. Most callers should use the package-level Get and Put convenience functions rather than creating their own Pool.

Functions

func Get

func Get(minCapacity int) []byte

Get returns a byte slice with len == 0 and cap >= minCapacity from the DefaultPool.

func Marshal

func Marshal(m Marshaler) ([]byte, error)

Marshal serializes m into a pool-sourced buffer and returns the buffer containing the serialized data. It calls m.Size to determine the exact serialized size, obtains a buffer of that capacity from the DefaultPool, and calls m.MarshalAppend to serialize into it.

The caller is responsible for calling Put on the returned buffer when it is no longer needed, to return the backing memory to the pool.

func Put

func Put(buf []byte)

Put returns buf to the DefaultPool for future reuse.

Types

type MarshalAppender

type MarshalAppender interface {
	MarshalAppend(b []byte) ([]byte, error)
}

MarshalAppender is the interface for append-style serialization. An implementation appends the serialized form of the receiver to b and returns the extended slice. The error return covers message-level failures such as required fields missing or values out of range; wire-level encoding functions in the wire/ and scalar/ packages are infallible and do not need this error path.

type Marshaler

type Marshaler interface {
	MarshalAppender
	Sizer
}

Marshaler is the combined interface for types that support the full zero-allocation serialization workflow: pre-compute the size via Sizer, obtain a pool buffer of the exact capacity, and serialize via MarshalAppender. This composition follows the Interface Segregation Principle (ISP) pattern established in wire/codec.go: callers that only need sizing accept Sizer, callers that only need encoding accept MarshalAppender, and callers that need both accept Marshaler.

type Pool

type Pool struct {
	// contains filtered or unexported fields
}

Pool is a sync.Pool-based buffer pool with power-of-2 size-class bucketing. Each size class maintains its own sync.Pool to reduce fragmentation and improve reuse rates. Buffers are stored as *[]byte (pointer to slice) to avoid interface allocation overhead on the Get/Put hot path. A parallel ptrs array recycles the *[]byte pointer wrappers so that Put avoids allocating new([]byte) on each call.

func NewPool

func NewPool() *Pool

NewPool returns a pointer to a new Pool with each size class initialized. Each sync.Pool is configured with a New function that allocates a *[]byte of the correct class capacity. The ptrs pools lazily allocate *[]byte pointer wrappers that are recycled across Get/Put cycles.

func (*Pool) Get

func (p *Pool) Get(minCapacity int) []byte

Get returns a byte slice with len == 0 and cap >= minCapacity. When a matching buffer exists in the pool, Get reuses it with zero heap allocations. If minCapacity exceeds maxPooledSize, a fresh slice is allocated directly without using the pool.

func (*Pool) Put

func (p *Pool) Put(buf []byte)

Put returns buf to the pool for future reuse. Nil slices, zero-capacity slices, and slices exceeding maxPooledSize are silently discarded. Put reuses a recycled *[]byte pointer from the pointer pool to avoid heap allocation on the hot path.

type Sizer

type Sizer interface {
	Size() int
}

Sizer is the interface for deterministic size pre-computation. An implementation returns the exact number of bytes the serialized form will occupy, computed without allocations and without performing any encoding. Calling Size multiple times on an unmodified value must return the same result.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL