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 ¶
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 Marshal ¶
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.
Types ¶
type MarshalAppender ¶
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.
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.