scratch

package
v0.16.1 Latest Latest
Warning

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

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

README

scratch

Shared, size-bounded buffer recycling for the SDK's service codecs.

scratch centralises the *bytes.Buffer pooling that every codec previously reimplemented: one shared sync.Pool, one cap-discard threshold, one acquire/release pair.

API

const MaxRetainedBufBytes = 256 << 10

func AcquireBuffer() *bytes.Buffer    // returns an already-Reset buffer
func ReleaseBuffer(buf *bytes.Buffer) // repools, or drops if Cap > MaxRetainedBufBytes

func AcquireReader(src []byte) *bytes.Reader // returns a reader positioned at src
func ReleaseReader(r *bytes.Reader)          // repools (no cap-discard — fixed-size)

Usage

buf := scratch.AcquireBuffer()
// ... encode into buf ...
out := slices.Clone(buf.Bytes()) // clone before release if bytes escape
scratch.ReleaseBuffer(buf)
return out

Lifetime

A buffer is caller-owned from AcquireBuffer until ReleaseBuffer. After release, neither the buffer nor any slice aliasing buf.Bytes() may be used. Clone the encoded bytes first if they must outlive the release.

A single shared pool is used deliberately: sync.Pool is per-P sharded, so consolidation raises the reuse rate without adding contention.

This package is internal to the SDK; consumers reach codecs through pkg/v1/codec.

Documentation

Overview

Package scratch provides shared, size-bounded recycling primitives for the service codecs. Every codec that encodes into a transient *bytes.Buffer previously declared its own sync.Pool, its own 256 KiB cap-discard constant, and its own release helper. Centralising them here gives a single source of truth for the cap-discard policy and a single shared pool whose reuse rate is higher than nine independent pools (sync.Pool is internally per-P sharded, so consolidation does not add contention).

The pooling MECHANISM lives in internal/kernel/recycler (ADR 0010); scratch is a codec-domain consumer that keeps the 256 KiB threshold and the concrete *bytes.Buffer / *bytes.Reader types here.

Lifetime contract: a value returned by an Acquire* call is owned by the caller until the matching Release* call. After Release the value — and any slice aliasing it (e.g. buf.Bytes()) — MUST NOT be used; clone the encoded bytes first if they need to outlive the release.

Index

Constants

View Source
const MaxRetainedBufBytes int = 256 << 10

MaxRetainedBufBytes is the project-wide cap-discard threshold for pooled *bytes.Buffer instances. A buffer whose capacity exceeds this is dropped on release rather than re-pooled, so a one-off oversized payload cannot pin a large allocation for the lifetime of the pool's GC window.

Variables

This section is empty.

Functions

func AcquireBuffer

func AcquireBuffer() *bytes.Buffer

AcquireBuffer returns a clean, zero-length *bytes.Buffer from the shared pool. The recycler reset the buffer on its previous Put, so callers append directly without re-resetting. The caller owns it until ReleaseBuffer.

func AcquireReader

func AcquireReader(src []byte) *bytes.Reader

AcquireReader returns a *bytes.Reader from the shared pool, reset to read from src. The caller owns it until ReleaseReader; src must stay alive and unmodified for as long as the reader is used.

func ReleaseBuffer

func ReleaseBuffer(buf *bytes.Buffer)

ReleaseBuffer returns buf to the shared pool unless its capacity exceeds MaxRetainedBufBytes, in which case the recycler orphans it for the GC. Callers MUST NOT use buf — or any slice aliasing buf.Bytes() — after this call; clone first if the encoded bytes must outlive the release.

func ReleaseReader

func ReleaseReader(r *bytes.Reader)

ReleaseReader returns r to the shared pool. A bytes.Reader is fixed-size, so there is no cap-discard. Callers MUST NOT use r after this call.

Types

This section is empty.

Jump to

Keyboard shortcuts

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