iobuf

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Jan 1, 2026 License: MIT Imports: 7 Imported by: 0

README

iobuf

Go Reference Go Report Card codecov

Lock-free, memory-friendly bounded buffer pools for Go optimized for low-latency systems.

English | 简体中文 | Español | 日本語 | Français

Three-Tier Progress Model

iobuf utilizes the Spin and Adapt layers of our performance ecosystem:

  1. Strike: System call → Direct kernel hit.
  2. Spin: Hardware yield (spin) → Local atomic synchronization.
  3. Adapt: Software backoff (iox.Backoff) → External I/O readiness.

Features

  • Bounded lock-free buffer pools for low-latency systems.
  • Page-aligned memory allocation for DMA and io_uring compatibility.
  • Zero-copy IoVec generation for vectored I/O syscalls.
  • Cooperative back-off: Uses iox.Backoff to handle resource exhaustion gracefully.

Requirements

  • Go 1.25+
  • 64-bit CPU (amd64, arm64, riscv64, loong64, ppc64, s390x, mips64, etc.)

Note: 32-bit architectures are not supported due to 64-bit atomic operations in the lock-free pool implementation.

Installation

go get code.hybscloud.com/iobuf

Quick Start

Buffer Pools
// Create a pool of 1024 small buffers (2 KiB each)
pool := iobuf.NewSmallBufferPool(1024)
pool.Fill(iobuf.NewSmallBuffer)

// Acquire a buffer index
idx, err := pool.Get()
if err != nil {
    panic(err)
}

// Access the buffer directly (zero-copy)
buf := pool.Value(idx)
...

// Return to pool
pool.Put(idx)
Page-Aligned Memory
// Single page-aligned block (default page size)
block := iobuf.AlignedMemBlock()

// Custom size with explicit alignment
mem := iobuf.AlignedMem(65536, iobuf.PageSize)

// Multiple aligned blocks
blocks := iobuf.AlignedMemBlocks(16, iobuf.PageSize)
IoVec for Vectored I/O
// Convert tiered buffers to iovec for readv/writev
buffers := make([]iobuf.SmallBuffer, 8)
iovecs := iobuf.IoVecFromSmallBuffers(buffers)

// Get raw pointer and count for syscalls
addr, n := iobuf.IoVecAddrLen(iovecs)

Buffer Tiers

Power-of-4 progression starting at 32 bytes (12 tiers, 32 B to 128 MiB):

Tier Size Use Case
Pico 32 B UUIDs, flags, tiny control messages
Nano 128 B HTTP headers, JSON tokens, small RPC payloads
Micro 512 B DNS packets, MQTT messages, protocol frames
Small 2 KiB WebSocket frames, small HTTP responses
Medium 8 KiB TCP segments, gRPC messages, page I/O
Big 32 KiB TLS records (16 KiB max), stream chunks
Large 128 KiB io_uring buffer rings, bulk network transfers
Great 512 KiB Database pages, large API responses
Huge 2 MiB Huge page aligned, memory-mapped files
Vast 8 MiB Image processing, compressed archives
Giant 32 MiB Video frames, ML model weights
Titan 128 MiB Large datasets, maximum stack-safe buffer

API Overview

Pool Interfaces
// Generic pool interface
type Pool[T any] interface {
    Put(item T) error
    Get() (item T, err error)
}

// Index-based pool for zero-copy buffer access
type IndirectPool[T BufferType] interface {
    Pool[int]
    Value(indirect int) T
    SetValue(indirect int, item T)
}
Pool Constructors
func NewPicoBufferPool(capacity int) *PicoBufferBoundedPool
func NewNanoBufferPool(capacity int) *NanoBufferBoundedPool
func NewMicroBufferPool(capacity int) *MicroBufferBoundedPool
func NewSmallBufferPool(capacity int) *SmallBufferBoundedPool
func NewMediumBufferPool(capacity int) *MediumBufferBoundedPool
func NewBigBufferPool(capacity int) *BigBufferBoundedPool
func NewLargeBufferPool(capacity int) *LargeBufferBoundedPool
func NewGreatBufferPool(capacity int) *GreatBufferBoundedPool
func NewHugeBufferPool(capacity int) *HugeBufferBoundedPool
func NewVastBufferPool(capacity int) *VastBufferBoundedPool
func NewGiantBufferPool(capacity int) *GiantBufferBoundedPool
func NewTitanBufferPool(capacity int) *TitanBufferBoundedPool
Memory Allocation
// Page-aligned memory
func AlignedMem(size int, pageSize uintptr) []byte
func AlignedMemBlocks(n int, pageSize uintptr) [][]byte
func AlignedMemBlock() []byte

// Cache-line-aligned memory (prevents false sharing)
func CacheLineAlignedMem(size int) []byte
func CacheLineAlignedMemBlocks(n int, blockSize int) [][]byte
const CacheLineSize  // 64 or 128 depending on architecture
IoVec Generation
func IoVecFromBytesSlice(iov [][]byte) (addr uintptr, n int)
func IoVecFromPicoBuffers(buffers []PicoBuffer) []IoVec
// ... and for all other tiers

Design

The bounded pool implementation is based on lock-free queue algorithms:

  • Memory-efficient: O(n) space for n-capacity pool
  • Lock-free progress: Guaranteed global progress bounds
  • Cache-friendly: Minimizes false sharing and cache-line bouncing

References

License

MIT License - see LICENSE for details.

© 2025 Hayabusa Cloud Co., Ltd.

Documentation

Overview

Package iobuf provides lock-free buffer pools and memory management utilities for high-performance I/O operations.

The package implements a 12-tier buffer size hierarchy and lock-free bounded pools optimized for zero-allocation hot paths. All pools use semantic error types from iox for non-blocking control flow.

Buffer Tiers

Buffers are organized into 12 size tiers following a power-of-4 progression:

Tier      Size       Use Case
────      ────       ────────
Pico      32 B       Tiny metadata, flags
Nano      128 B      Small headers, control frames
Micro     512 B      Protocol frames, small messages
Small     2 KiB      Typical network packets
Medium    8 KiB      Stream buffers, large packets
Big       32 KiB     TLS records, stream chunks
Large     128 KiB    io_uring buffer rings
Great     512 KiB    Large transfers
Huge      2 MiB      Huge page aligned buffers
Vast      8 MiB      Large file chunks
Giant     32 MiB     Video frames, datasets
Titan     128 MiB    Maximum allocation tier

Each tier has corresponding type aliases (e.g., SmallBuffer, LargeBuffer) and factory functions for bounded pools (e.g., NewSmallBufferPool).

Bounded Pool

BoundedPool is a lock-free multi-producer multi-consumer (MPMC) pool based on the algorithm from "A Scalable, Portable, and Memory-Efficient Lock-Free FIFO Queue" (Ruslan Nikolaev, 2019). Key characteristics:

  • Lock-free: Uses atomic CAS operations, no mutexes
  • Bounded: Fixed capacity rounded to power of two
  • Memory-efficient: Single contiguous array, no per-element allocation
  • Cache-optimized: Aligned to cache line boundaries to prevent false sharing

Indirect Pool Pattern

Pools store indices (int) rather than buffer values directly. This enables:

  • Zero-copy access via Value(indirect) method
  • Efficient pool operations without moving large buffers
  • Clear ownership semantics through index hand-off

Usage pattern:

pool := NewSmallBufferPool(100) // Creates pool with ~128 capacity
pool.Fill(NewSmallBuffer)       // Initialize with buffer factory
idx, err := pool.Get()          // Acquire buffer index
if err != nil {
    // Handle iox.ErrWouldBlock (pool empty)
}
buf := pool.Value(idx)          // Access buffer by index
// Use buf[:]...
pool.Put(idx)                   // Return buffer to pool

Page-Aligned Memory

For DMA and io_uring operations requiring page alignment:

mem := AlignedMem(4096, PageSize)  // Returns page-aligned []byte
block := AlignedMemBlock()         // Single page using default PageSize
blocks := AlignedMemBlocks(16, PageSize) // Multiple aligned blocks

Vectored I/O

IoVec provides scatter/gather I/O support for readv/writev syscalls:

buffers := make([]SmallBuffer, 8)
iovecs := IoVecFromSmallBuffers(buffers)
addr, n := IoVecAddrLen(iovecs)  // Get pointer for syscall

Architecture Requirements

This package requires a 64-bit CPU architecture (amd64, arm64, riscv64, loong64, ppc64, ppc64le, s390x, mips64, mips64le). 32-bit architectures are not supported due to 64-bit atomic operations in BoundedPool.

Thread Safety

All pool operations are safe for concurrent use. BoundedPool supports multiple concurrent producers and consumers without external synchronization.

Dependencies

iobuf depends on:

  • iox: Semantic error types (ErrWouldBlock, ErrMore)
  • spin: Spinlock and spin-wait primitives for backpressure

Index

Constants

View Source
const (
	BufferSizePico   = 1 << 5  // 32 B - tiny metadata, flags
	BufferSizeNano   = 1 << 7  // 128 B - small structs, headers
	BufferSizeMicro  = 1 << 9  // 512 B - protocol frames
	BufferSizeSmall  = 1 << 11 // 2 KiB - small messages
	BufferSizeMedium = 1 << 13 // 8 KiB - stream buffers
	BufferSizeBig    = 1 << 15 // 32 KiB - TLS records
	BufferSizeLarge  = 1 << 17 // 128 KiB - io_uring buffers
	BufferSizeGreat  = 1 << 19 // 512 KiB - large transfers
	BufferSizeHuge   = 1 << 21 // 2 MiB - huge pages
	BufferSizeVast   = 1 << 23 // 8 MiB - large file chunks
	BufferSizeGiant  = 1 << 25 // 32 MiB - video frames
	BufferSizeTitan  = 1 << 27 // 128 MiB - maximum buffer tier
)

Buffer size tiers follow a power-of-4 progression starting at 32 bytes. Each tier is 4x the previous size, optimized for different I/O patterns. 12 tiers: 32B, 128B, 512B, 2KiB, 8KiB, 32KiB, 128KiB, 512KiB, 2MiB, 8MiB, 32MiB, 128MiB

View Source
const CacheLineSize = internal.CacheLineSize

CacheLineSize is the CPU L1 cache line size for the current architecture. This is detected at compile time based on the target architecture:

  • amd64: 64 bytes (Intel/AMD)
  • arm64: 128 bytes (conservative for Apple Silicon)
  • riscv64: 64 bytes
  • loong64: 64 bytes
  • others: 64 bytes (default)

Variables

View Source
var PageSize uintptr = 4096

PageSize is the memory page size used for aligned allocations.

The default value (4 KiB) matches the typical x86-64 and ARM64 page size. Use SetPageSize to configure for systems with different page sizes.

Functions

func AlignedMem

func AlignedMem(size int, pageSize uintptr) []byte

AlignedMem returns a byte slice with the specified size and starting address aligned to the memory page size.

This is useful for DMA operations and io_uring registered buffers that require page-aligned memory addresses.

The returned slice shares underlying memory with a larger allocation; do not assume len(result) == cap(result).

func AlignedMemBlock

func AlignedMemBlock() []byte

AlignedMemBlock returns a single page-aligned block using the system page size.

This is a convenience function equivalent to AlignedMemBlocks(1, PageSize)[0].

func AlignedMemBlocks

func AlignedMemBlocks(n int, pageSize uintptr) (blocks [][]byte)

AlignedMemBlocks returns n page-aligned byte slices, each of length pageSize.

All returned slices share a single contiguous underlying allocation, which is more memory-efficient than calling AlignedMem n times.

Panics if n < 1.

func BufferSizeFor added in v0.2.0

func BufferSizeFor(size int) int

BufferSizeFor returns the smallest buffer size that can hold 'size' bytes. This is a convenience function equivalent to TierBySize(size).Size().

func CacheLineAlignedMem added in v0.2.0

func CacheLineAlignedMem(size int) []byte

CacheLineAlignedMem returns a byte slice with the specified size and starting address aligned to the CPU cache line size. This is useful for preventing false sharing in concurrent data structures.

func CacheLineAlignedMemBlocks added in v0.2.0

func CacheLineAlignedMemBlocks(n int, blockSize int) (blocks [][]byte)

CacheLineAlignedMemBlocks returns n cache-line-aligned byte slices, each of length blockSize. Adjacent blocks are separated by cache line boundaries to prevent false sharing.

func IoVecAddrLen

func IoVecAddrLen(vec []IoVec) (addr uintptr, n int)

IoVecAddrLen extracts the raw pointer and length from an IoVec slice for direct syscall consumption (readv, writev, io_uring submission).

Returns (0, 0) for empty or nil slices.

func IoVecFromBytesSlice

func IoVecFromBytesSlice(iov [][]byte) (addr uintptr, n int)

IoVecFromBytesSlice converts a slice of byte slices to a pointer and count suitable for io_uring buffer registration (IORING_REGISTER_BUFFERS2). Returns the address of the first IoVec element and the number of elements.

Note: The returned address points to a newly allocated []IoVec slice. The caller must ensure the input slices remain valid for the lifetime of the registration.

func SetPageSize

func SetPageSize(size int)

SetPageSize updates the package-level page size used for aligned allocations.

This should be called once during initialization, before any calls to AlignedMem or AlignedMemBlocks. Common values:

  • 4096 (4 KiB): Standard x86-64, ARM64
  • 16384 (16 KiB): Some ARM64 configurations (Apple Silicon)
  • 65536 (64 KiB): Some embedded systems

Types

type BigBuffer added in v0.2.0

type BigBuffer [BufferSizeBig]byte

BigBuffer is a 32 KiB buffer for TLS records.

func BigArrayFromSlice added in v0.2.0

func BigArrayFromSlice(s []byte, offset int64) BigBuffer

BigArrayFromSlice returns a BigBuffer by copying from the slice at the given offset.

func NewBigBuffer added in v0.2.0

func NewBigBuffer() BigBuffer

NewBigBuffer returns a zero-initialized BigBuffer.

func SliceOfBigArray added in v0.2.0

func SliceOfBigArray(s []byte, offset int64, n int) []BigBuffer

SliceOfBigArray returns a slice of BigBuffer views of the underlying slice starting at offset.

func (BigBuffer) Reset added in v0.2.0

func (b BigBuffer) Reset()

type BigBufferBoundedPool added in v0.2.0

type BigBufferBoundedPool = BoundedPool[BigBuffer]

BigBufferBoundedPool implements a bounded MPMC pool for 32 KiB buffers.

func NewBigBufferPool added in v0.2.0

func NewBigBufferPool(capacity int) *BigBufferBoundedPool

NewBigBufferPool creates a new instance of BigBufferBoundedPool with the specified capacity. The capacity must be between 1 and math.MaxUint32 and will be rounded up to the next power of two.

type BigBufferPool added in v0.2.0

type BigBufferPool = IndirectPool[BigBuffer]

BigBufferPool manages 32 KiB buffers via indirect indexing.

type BoundedPool

type BoundedPool[T BoundedPoolItem] struct {
	// contains filtered or unexported fields
}

BoundedPool is a generic type that represents a bounded pool of items of type T. The pool has a bounded and fixed capacity and allows items to be retrieved and returned. If the pool is empty and the non-blocking mode is not set, Get() calls would block until an item is available. If the pool is full and the non-blocking mode is not set, Put() calls would block until the BoundedPool is no longer full. BoundedPool is safe for concurrent use. The Get() and Put() methods ensure that at least one of the goroutines makes progress. The implementation of BoundedPool is based on the algorithms in the following paper:

https://nikitakoval.org/publications/ppopp20-queues.pdf

Usage:

pool := NewBoundedPool[ItemType](capacity) creates a new instance of BoundedPool with the specified capacity.
pool.Fill(newFunc) initializes and fills the pool with a function to create new items.
pool.SetNonblock(nonblocking) enables or disables the non-blocking mode of the pool.
pool.Value(indirect) returns the item at the specified indirect index.
pool.SetValue(indirect, val) sets the value of the item at the specified indirect index in pool.
pool.Get() retrieves an item from the pool and returns its indirect index.
pool.Put(indirect) puts the indirect index of an item back into the pool.

func NewBoundedPool

func NewBoundedPool[ItemType BoundedPoolItem](capacity int) *BoundedPool[ItemType]

NewBoundedPool creates a lock-free bounded pool with the specified capacity.

The capacity is rounded up to the next power of two for efficient index calculation. The actual capacity can be retrieved via Cap().

Panics if capacity < 1 or capacity > math.MaxUint32.

After creation, Fill must be called before Get/Put operations.

func (*BoundedPool[T]) Cap

func (pool *BoundedPool[T]) Cap() int

Cap returns the actual capacity of the BoundedPool.

This may be larger than the requested capacity due to power-of-two rounding.

func (*BoundedPool[T]) Fill

func (pool *BoundedPool[T]) Fill(newFunc func() T)

Fill initializes and fills the BoundedPool with a newFunc function, which is used to create new items. Fill Put capacity items with new BoundedPoolItem created by newFunc for each item in the pool.

Example:

pool := NewBoundedPool[ItemType](capacity)
pool.Fill(newFunc)

Parameters:

newFunc - a function that returns an instance of an item to be added to the pool.

func (*BoundedPool[T]) Get

func (pool *BoundedPool[T]) Get() (indirect int, err error)

Get retrieves an item from the pool and returns its indirect index. If an item is available, its indirect index and a nil error are returned. Returns iox.ErrWouldBlock if the pool is empty and nonblocking mode is set.

In blocking mode, Get uses adaptive waiting (iox.Backoff) when the pool is empty. This acknowledges that buffer exhaustion is an external I/O event—buffers are released when the kernel/network finishes processing— requiring OS-level sleep rather than hardware-level spin.

func (*BoundedPool[T]) Put

func (pool *BoundedPool[T]) Put(indirect int) error

Put puts the indirect index of an item back into the BoundedPool. It tries to put the given indirect index into the pool and returns nil error if successful. If the BoundedPool is currently full, it would block until the item can be put into the pool or return iox.ErrWouldBlock if the pool is nonblocking.

In blocking mode, Put uses adaptive waiting (iox.Backoff) when the pool is full. This acknowledges that pool capacity is freed by external consumers completing their I/O operations.

func (*BoundedPool[T]) SetNonblock

func (pool *BoundedPool[T]) SetNonblock(nonblocking bool)

SetNonblock enables or disables the non-blocking mode of the pool. When nonblocking is set to true, Get() and Put() calls will not block and return immediately. When nonblocking is set to false, Get() calls will block until an item is available, and Put() calls will block until the pool is no longer full.

Example:

pool := NewBoundedPool[ItemType](capacity)
pool.SetNonblock(true)

Parameters:

nonblocking - determines whether the pool operates in non-blocking mode (true) or blocking mode (false).

func (*BoundedPool[T]) SetValue

func (pool *BoundedPool[T]) SetValue(indirect int, value T)

SetValue sets the value of the item at the specified indirect index in the BoundedPool. The given indirect index must not be marked as empty and must be within the valid range.

func (*BoundedPool[T]) Value

func (pool *BoundedPool[T]) Value(indirect int) T

Value returns the item at the specified indirect index. The given indirect index must not be marked as empty and must be within the valid range.

type BoundedPoolItem

type BoundedPoolItem interface{}

BoundedPoolItem is a type constraint for items stored in a BoundedPool.

Any type can satisfy this interface. The constraint exists to make the generic type parameter explicit and to allow future extension.

type BufferTier added in v0.2.0

type BufferTier int

BufferTier represents a buffer tier index in the 12-tier system.

const (
	TierPico BufferTier = iota
	TierNano
	TierMicro
	TierSmall
	TierMedium
	TierBig
	TierLarge
	TierGreat
	TierHuge
	TierVast
	TierGiant
	TierTitan
	TierEnd // Sentinel marking end of tiers
)

Buffer tier indices for the 12-tier buffer system.

func TierBySize added in v0.2.0

func TierBySize(size int) BufferTier

TierBySize returns the smallest buffer tier that can hold 'size' bytes. Returns TierTitan for sizes larger than BufferSizeTitan.

func (BufferTier) Size added in v0.2.0

func (t BufferTier) Size() int

Size returns the buffer size for this tier.

type BufferType

BufferType is a type constraint for tiered buffer types.

type Buffers

type Buffers = net.Buffers

Buffers is an alias for net.Buffers, providing a standard way to group multiple byte slices for vectored I/O operations.

func NewBuffers

func NewBuffers(n int, size int) Buffers

NewBuffers creates a Buffers slice containing n byte slices, each of length size.

Returns an empty Buffers if n < 1. Each inner slice is independently allocated; for contiguous memory, use AlignedMemBlocks instead.

type GiantBuffer

type GiantBuffer [BufferSizeGiant]byte

GiantBuffer is a 32 MiB buffer for video frames and datasets.

func GiantArrayFromSlice

func GiantArrayFromSlice(s []byte, offset int64) GiantBuffer

GiantArrayFromSlice returns a GiantBuffer by copying from the slice at the given offset.

func NewGiantBuffer

func NewGiantBuffer() GiantBuffer

NewGiantBuffer returns a zero-initialized GiantBuffer.

func SliceOfGiantArray

func SliceOfGiantArray(s []byte, offset int64, n int) []GiantBuffer

SliceOfGiantArray returns a slice of GiantBuffer views of the underlying slice starting at offset.

func (GiantBuffer) Reset

func (b GiantBuffer) Reset()

type GiantBufferBoundedPool

type GiantBufferBoundedPool = BoundedPool[GiantBuffer]

GiantBufferBoundedPool implements a bounded MPMC pool for 32 MiB buffers.

func NewGiantBufferPool

func NewGiantBufferPool(capacity int) *GiantBufferBoundedPool

NewGiantBufferPool creates a new instance of GiantBufferBoundedPool with the specified capacity. The capacity must be between 1 and math.MaxUint32 and will be rounded up to the next power of two.

type GiantBufferPool

type GiantBufferPool = IndirectPool[GiantBuffer]

GiantBufferPool manages 32 MiB buffers via indirect indexing.

type GreatBuffer added in v0.2.0

type GreatBuffer [BufferSizeGreat]byte

GreatBuffer is a 512 KiB buffer for large transfers.

func GreatArrayFromSlice added in v0.2.0

func GreatArrayFromSlice(s []byte, offset int64) GreatBuffer

GreatArrayFromSlice returns a GreatBuffer by copying from the slice at the given offset.

func NewGreatBuffer added in v0.2.0

func NewGreatBuffer() GreatBuffer

NewGreatBuffer returns a zero-initialized GreatBuffer.

func SliceOfGreatArray added in v0.2.0

func SliceOfGreatArray(s []byte, offset int64, n int) []GreatBuffer

SliceOfGreatArray returns a slice of GreatBuffer views of the underlying slice starting at offset.

func (GreatBuffer) Reset added in v0.2.0

func (b GreatBuffer) Reset()

type GreatBufferBoundedPool added in v0.2.0

type GreatBufferBoundedPool = BoundedPool[GreatBuffer]

GreatBufferBoundedPool implements a bounded MPMC pool for 512 KiB buffers.

func NewGreatBufferPool added in v0.2.0

func NewGreatBufferPool(capacity int) *GreatBufferBoundedPool

NewGreatBufferPool creates a new instance of GreatBufferBoundedPool with the specified capacity. The capacity must be between 1 and math.MaxUint32 and will be rounded up to the next power of two.

type GreatBufferPool added in v0.2.0

type GreatBufferPool = IndirectPool[GreatBuffer]

GreatBufferPool manages 512 KiB buffers via indirect indexing.

type HugeBuffer

type HugeBuffer [BufferSizeHuge]byte

HugeBuffer is a 2 MiB buffer matching huge page sizes.

func HugeArrayFromSlice

func HugeArrayFromSlice(s []byte, offset int64) HugeBuffer

HugeArrayFromSlice returns a HugeBuffer by copying from the slice at the given offset.

func NewHugeBuffer

func NewHugeBuffer() HugeBuffer

NewHugeBuffer returns a zero-initialized HugeBuffer.

func SliceOfHugeArray

func SliceOfHugeArray(s []byte, offset int64, n int) []HugeBuffer

SliceOfHugeArray returns a slice of HugeBuffer views of the underlying slice starting at offset.

func (HugeBuffer) Reset

func (b HugeBuffer) Reset()

type HugeBufferBoundedPool

type HugeBufferBoundedPool = BoundedPool[HugeBuffer]

HugeBufferBoundedPool implements a bounded MPMC pool for 2 MiB buffers.

func NewHugeBufferPool

func NewHugeBufferPool(capacity int) *HugeBufferBoundedPool

NewHugeBufferPool creates a new instance of HugeBufferBoundedPool with the specified capacity. The capacity must be between 1 and math.MaxUint32 and will be rounded up to the next power of two.

type HugeBufferPool

type HugeBufferPool = IndirectPool[HugeBuffer]

HugeBufferPool manages 2 MiB buffers via indirect indexing.

type IndirectPool

type IndirectPool[T BufferType] interface {
	Pool[int]

	// Value returns the buffer associated with the given indirect index.
	// The caller must have acquired this index via Get.
	Value(indirect int) T

	// SetValue updates the buffer at the specified indirect index.
	// The caller must have acquired this index via Get.
	SetValue(indirect int, item T)
}

IndirectPool manages items by index rather than by value, enabling zero-copy access to pooled buffers.

The pool stores buffer indices (int) rather than buffer values directly. This design allows:

  • Zero-copy buffer access via Value() without moving large buffers
  • Efficient pool operations (only small integers are enqueued/dequeued)
  • Clear ownership semantics through index hand-off

Usage pattern:

idx, _ := pool.Get()     // Acquire buffer index
buf := pool.Value(idx)   // Access buffer by index
// Use buf[:]...
pool.Put(idx)            // Return buffer to pool

type IoVec

type IoVec struct {
	Base *byte  // Starting address of the memory block
	Len  uint64 // Number of bytes to transfer
}

IoVec represents a scatter/gather I/O descriptor compatible with the standard Linux struct iovec. It is used to pass multiple non-contiguous user-space buffers to the kernel in a single vectored I/O system call (readv, writev, preadv, pwritev, io_uring operations).

Memory layout matches the C struct iovec exactly:

struct iovec {
    void  *iov_base;  // Starting address
    size_t iov_len;   // Number of bytes
};

The caller must ensure Base points to valid memory for the lifetime of any I/O operation using this IoVec.

func IoVecFromBigBuffers added in v0.2.0

func IoVecFromBigBuffers(buffers []BigBuffer) []IoVec

IoVecFromBigBuffers converts a slice of BigBuffer to an IoVec slice. The returned IoVec elements point directly to the buffer memory without copying.

func IoVecFromGiantBuffers

func IoVecFromGiantBuffers(buffers []GiantBuffer) []IoVec

IoVecFromGiantBuffers converts a slice of GiantBuffer to an IoVec slice. The returned IoVec elements point directly to the buffer memory without copying.

func IoVecFromGreatBuffers added in v0.2.0

func IoVecFromGreatBuffers(buffers []GreatBuffer) []IoVec

IoVecFromGreatBuffers converts a slice of GreatBuffer to an IoVec slice. The returned IoVec elements point directly to the buffer memory without copying.

func IoVecFromHugeBuffers

func IoVecFromHugeBuffers(buffers []HugeBuffer) []IoVec

IoVecFromHugeBuffers converts a slice of HugeBuffer to an IoVec slice. The returned IoVec elements point directly to the buffer memory without copying.

func IoVecFromLargeBuffers

func IoVecFromLargeBuffers(buffers []LargeBuffer) []IoVec

IoVecFromLargeBuffers converts a slice of LargeBuffer to an IoVec slice. The returned IoVec elements point directly to the buffer memory without copying.

func IoVecFromMediumBuffers

func IoVecFromMediumBuffers(buffers []MediumBuffer) []IoVec

IoVecFromMediumBuffers converts a slice of MediumBuffer to an IoVec slice. The returned IoVec elements point directly to the buffer memory without copying.

func IoVecFromMicroBuffers

func IoVecFromMicroBuffers(buffers []MicroBuffer) []IoVec

IoVecFromMicroBuffers converts a slice of MicroBuffer to an IoVec slice. The returned IoVec elements point directly to the buffer memory without copying.

func IoVecFromNanoBuffers

func IoVecFromNanoBuffers(buffers []NanoBuffer) []IoVec

IoVecFromNanoBuffers converts a slice of NanoBuffer to an IoVec slice. The returned IoVec elements point directly to the buffer memory without copying.

func IoVecFromPicoBuffers

func IoVecFromPicoBuffers(buffers []PicoBuffer) []IoVec

IoVecFromPicoBuffers converts a slice of PicoBuffer to an IoVec slice. The returned IoVec elements point directly to the buffer memory without copying.

func IoVecFromRegisteredBuffers

func IoVecFromRegisteredBuffers(buffers []RegisterBuffer) []IoVec

IoVecFromRegisteredBuffers converts a slice of RegisterBuffer to an IoVec slice. The returned IoVec elements point directly to the buffer memory without copying.

func IoVecFromSmallBuffers

func IoVecFromSmallBuffers(buffers []SmallBuffer) []IoVec

IoVecFromSmallBuffers converts a slice of SmallBuffer to an IoVec slice. The returned IoVec elements point directly to the buffer memory without copying.

func IoVecFromTitanBuffers added in v0.2.0

func IoVecFromTitanBuffers(buffers []TitanBuffer) []IoVec

IoVecFromTitanBuffers converts a slice of TitanBuffer to an IoVec slice. The returned IoVec elements point directly to the buffer memory without copying.

func IoVecFromVastBuffers added in v0.2.0

func IoVecFromVastBuffers(buffers []VastBuffer) []IoVec

IoVecFromVastBuffers converts a slice of VastBuffer to an IoVec slice. The returned IoVec elements point directly to the buffer memory without copying.

type LargeBuffer

type LargeBuffer [BufferSizeLarge]byte

LargeBuffer is a 128 KiB buffer for io_uring buffer rings.

func LargeArrayFromSlice

func LargeArrayFromSlice(s []byte, offset int64) LargeBuffer

LargeArrayFromSlice returns a LargeBuffer by copying from the slice at the given offset.

func NewLargeBuffer

func NewLargeBuffer() LargeBuffer

NewLargeBuffer returns a zero-initialized LargeBuffer.

func SliceOfLargeArray

func SliceOfLargeArray(s []byte, offset int64, n int) []LargeBuffer

SliceOfLargeArray returns a slice of LargeBuffer views of the underlying slice starting at offset.

func (LargeBuffer) Reset

func (b LargeBuffer) Reset()

type LargeBufferBoundedPool

type LargeBufferBoundedPool = BoundedPool[LargeBuffer]

LargeBufferBoundedPool implements a bounded MPMC pool for 128 KiB buffers.

func NewLargeBufferPool

func NewLargeBufferPool(capacity int) *LargeBufferBoundedPool

NewLargeBufferPool creates a new instance of LargeBufferBoundedPool with the specified capacity. The capacity must be between 1 and math.MaxUint32 and will be rounded up to the next power of two.

type LargeBufferPool

type LargeBufferPool = IndirectPool[LargeBuffer]

LargeBufferPool manages 128 KiB buffers via indirect indexing.

type MediumBuffer

type MediumBuffer [BufferSizeMedium]byte

MediumBuffer is an 8 KiB buffer for stream buffers.

func MediumArrayFromSlice

func MediumArrayFromSlice(s []byte, offset int64) MediumBuffer

MediumArrayFromSlice returns a MediumBuffer by copying from the slice at the given offset.

func NewMediumBuffer

func NewMediumBuffer() MediumBuffer

NewMediumBuffer returns a zero-initialized MediumBuffer.

func SliceOfMediumArray

func SliceOfMediumArray(s []byte, offset int64, n int) []MediumBuffer

SliceOfMediumArray returns a slice of MediumBuffer views of the underlying slice starting at offset.

func (MediumBuffer) Reset

func (b MediumBuffer) Reset()

type MediumBufferBoundedPool

type MediumBufferBoundedPool = BoundedPool[MediumBuffer]

MediumBufferBoundedPool implements a bounded MPMC pool for 8 KiB buffers.

func NewMediumBufferPool

func NewMediumBufferPool(capacity int) *MediumBufferBoundedPool

NewMediumBufferPool creates a new instance of MediumBufferBoundedPool with the specified capacity. The capacity must be between 1 and math.MaxUint32 and will be rounded up to the next power of two.

type MediumBufferPool

type MediumBufferPool = IndirectPool[MediumBuffer]

MediumBufferPool manages 8 KiB buffers via indirect indexing.

type MicroBuffer

type MicroBuffer [BufferSizeMicro]byte

MicroBuffer is a 512-byte buffer for protocol frames.

func MicroArrayFromSlice

func MicroArrayFromSlice(s []byte, offset int64) MicroBuffer

MicroArrayFromSlice returns a MicroBuffer by copying from the slice at the given offset.

func NewMicroBuffer

func NewMicroBuffer() MicroBuffer

NewMicroBuffer returns a zero-initialized MicroBuffer.

func SliceOfMicroArray

func SliceOfMicroArray(s []byte, offset int64, n int) []MicroBuffer

SliceOfMicroArray returns a slice of MicroBuffer views of the underlying slice starting at offset.

func (MicroBuffer) Reset

func (b MicroBuffer) Reset()

type MicroBufferBoundedPool

type MicroBufferBoundedPool = BoundedPool[MicroBuffer]

MicroBufferBoundedPool implements a bounded MPMC pool for 512-byte buffers.

func NewMicroBufferPool

func NewMicroBufferPool(capacity int) *MicroBufferBoundedPool

NewMicroBufferPool creates a new instance of MicroBufferBoundedPool with the specified capacity. The capacity must be between 1 and math.MaxUint32 and will be rounded up to the next power of two.

type MicroBufferPool

type MicroBufferPool = IndirectPool[MicroBuffer]

MicroBufferPool manages 512-byte buffers via indirect indexing.

type NanoBuffer

type NanoBuffer [BufferSizeNano]byte

NanoBuffer is a 128-byte buffer for small structs and headers.

func NanoArrayFromSlice

func NanoArrayFromSlice(s []byte, offset int64) NanoBuffer

NanoArrayFromSlice returns a NanoBuffer by copying from the slice at the given offset.

func NewNanoBuffer

func NewNanoBuffer() NanoBuffer

NewNanoBuffer returns a zero-initialized NanoBuffer.

func SliceOfNanoArray

func SliceOfNanoArray(s []byte, offset int64, n int) []NanoBuffer

SliceOfNanoArray returns a slice of NanoBuffer views of the underlying slice starting at offset.

func (NanoBuffer) Reset

func (b NanoBuffer) Reset()

type NanoBufferBoundedPool

type NanoBufferBoundedPool = BoundedPool[NanoBuffer]

NanoBufferBoundedPool implements a bounded MPMC pool for 128-byte buffers.

func NewNanoBufferPool

func NewNanoBufferPool(capacity int) *NanoBufferBoundedPool

NewNanoBufferPool creates a new instance of NanoBufferBoundedPool with the specified capacity. The capacity must be between 1 and math.MaxUint32 and will be rounded up to the next power of two.

type NanoBufferPool

type NanoBufferPool = IndirectPool[NanoBuffer]

NanoBufferPool manages 128-byte buffers via indirect indexing.

type PicoBuffer

type PicoBuffer [BufferSizePico]byte

PicoBuffer is a 32-byte buffer for tiny metadata and flags.

func NewPicoBuffer

func NewPicoBuffer() PicoBuffer

NewPicoBuffer returns a zero-initialized PicoBuffer.

func PicoArrayFromSlice

func PicoArrayFromSlice(s []byte, offset int64) PicoBuffer

PicoArrayFromSlice returns a PicoBuffer by copying from the slice at the given offset.

The caller must ensure offset+BufferSizePico <= len(s). The returned array is a copy, not a view of the underlying slice.

func SliceOfPicoArray

func SliceOfPicoArray(s []byte, offset int64, n int) []PicoBuffer

SliceOfPicoArray returns a slice of n PicoBuffers viewed from the underlying slice.

The returned slice references the same memory as s[offset:]; modifications to either will be visible in both. The caller must ensure:

  • offset + n*BufferSizePico <= len(s)
  • n >= 1 (panics otherwise)

func (PicoBuffer) Reset

func (b PicoBuffer) Reset()

type PicoBufferBoundedPool

type PicoBufferBoundedPool = BoundedPool[PicoBuffer]

PicoBufferBoundedPool implements a bounded MPMC pool for 32-byte buffers.

func NewPicoBufferPool

func NewPicoBufferPool(capacity int) *PicoBufferBoundedPool

NewPicoBufferPool creates a new instance of PicoBufferBoundedPool with the specified capacity. The capacity must be between 1 and math.MaxUint32 and will be rounded up to the next power of two.

type PicoBufferPool

type PicoBufferPool = IndirectPool[PicoBuffer]

PicoBufferPool manages 32-byte buffers via indirect indexing.

type Pool

type Pool[T any] interface {
	// Put returns the item to the pool.
	// Returns iox.ErrWouldBlock if non-blocking and full.
	Put(item T) error

	// Get acquires an item from the pool.
	// Returns iox.ErrWouldBlock if non-blocking and empty.
	Get() (item T, err error)
}

Pool is a generic object pool interface with configurable blocking semantics.

Implementations may operate in blocking or non-blocking mode. In blocking mode, Get blocks until an item is available and Put blocks until space is available. In non-blocking mode, both operations return iox.ErrWouldBlock instead of blocking.

All implementations must be safe for concurrent use.

type RegisterBuffer

type RegisterBuffer [registerBufferSize]byte

RegisterBuffer represents a fixed-size buffer used for registering with the I/O ring.

type RegisterBufferPool

type RegisterBufferPool = BoundedPool[RegisterBuffer]

RegisterBufferPool represents a pool of fixed-size buffers used for registering with the I/O ring.

func NewRegisterBufferPool

func NewRegisterBufferPool(capacity int) *RegisterBufferPool

NewRegisterBufferPool creates a RegisterBufferPool for io_uring buffer registration.

The actual capacity is rounded up to the next power of two. RegisterBuffer uses LargeBuffer size (128 KiB), suitable for io_uring provided buffers.

type SmallBuffer

type SmallBuffer [BufferSizeSmall]byte

SmallBuffer is a 2 KiB buffer for small messages.

func NewSmallBuffer

func NewSmallBuffer() SmallBuffer

NewSmallBuffer returns a zero-initialized SmallBuffer.

func SliceOfSmallArray

func SliceOfSmallArray(s []byte, offset int64, n int) []SmallBuffer

SliceOfSmallArray returns a slice of SmallBuffer views of the underlying slice starting at offset.

func SmallArrayFromSlice

func SmallArrayFromSlice(s []byte, offset int64) SmallBuffer

SmallArrayFromSlice returns a SmallBuffer by copying from the slice at the given offset.

func (SmallBuffer) Reset

func (b SmallBuffer) Reset()

type SmallBufferBoundedPool

type SmallBufferBoundedPool = BoundedPool[SmallBuffer]

SmallBufferBoundedPool implements a bounded MPMC pool for 2 KiB buffers.

func NewSmallBufferPool

func NewSmallBufferPool(capacity int) *SmallBufferBoundedPool

NewSmallBufferPool creates a new instance of SmallBufferBoundedPool with the specified capacity. The capacity must be between 1 and math.MaxUint32 and will be rounded up to the next power of two.

type SmallBufferPool

type SmallBufferPool = IndirectPool[SmallBuffer]

SmallBufferPool manages 2 KiB buffers via indirect indexing.

type TitanBuffer added in v0.2.0

type TitanBuffer [BufferSizeTitan]byte

TitanBuffer is a 128 MiB buffer, the maximum buffer tier.

func NewTitanBuffer added in v0.2.0

func NewTitanBuffer() TitanBuffer

NewTitanBuffer returns a zero-initialized TitanBuffer.

func SliceOfTitanArray added in v0.2.0

func SliceOfTitanArray(s []byte, offset int64, n int) []TitanBuffer

SliceOfTitanArray returns a slice of TitanBuffer views of the underlying slice starting at offset.

func TitanArrayFromSlice added in v0.2.0

func TitanArrayFromSlice(s []byte, offset int64) TitanBuffer

TitanArrayFromSlice returns a TitanBuffer by copying from the slice at the given offset.

func (TitanBuffer) Reset added in v0.2.0

func (b TitanBuffer) Reset()

type TitanBufferBoundedPool added in v0.2.0

type TitanBufferBoundedPool = BoundedPool[TitanBuffer]

TitanBufferBoundedPool implements a bounded MPMC pool for 128 MiB buffers.

func NewTitanBufferPool added in v0.2.0

func NewTitanBufferPool(capacity int) *TitanBufferBoundedPool

NewTitanBufferPool creates a new instance of TitanBufferBoundedPool with the specified capacity. The capacity must be between 1 and math.MaxUint32 and will be rounded up to the next power of two.

type TitanBufferPool added in v0.2.0

type TitanBufferPool = IndirectPool[TitanBuffer]

TitanBufferPool manages 128 MiB buffers via indirect indexing.

type VastBuffer added in v0.2.0

type VastBuffer [BufferSizeVast]byte

VastBuffer is an 8 MiB buffer for large file chunks.

func NewVastBuffer added in v0.2.0

func NewVastBuffer() VastBuffer

NewVastBuffer returns a zero-initialized VastBuffer.

func SliceOfVastArray added in v0.2.0

func SliceOfVastArray(s []byte, offset int64, n int) []VastBuffer

SliceOfVastArray returns a slice of VastBuffer views of the underlying slice starting at offset.

func VastArrayFromSlice added in v0.2.0

func VastArrayFromSlice(s []byte, offset int64) VastBuffer

VastArrayFromSlice returns a VastBuffer by copying from the slice at the given offset.

func (VastBuffer) Reset added in v0.2.0

func (b VastBuffer) Reset()

type VastBufferBoundedPool added in v0.2.0

type VastBufferBoundedPool = BoundedPool[VastBuffer]

VastBufferBoundedPool implements a bounded MPMC pool for 8 MiB buffers.

func NewVastBufferPool added in v0.2.0

func NewVastBufferPool(capacity int) *VastBufferBoundedPool

NewVastBufferPool creates a new instance of VastBufferBoundedPool with the specified capacity. The capacity must be between 1 and math.MaxUint32 and will be rounded up to the next power of two.

type VastBufferPool added in v0.2.0

type VastBufferPool = IndirectPool[VastBuffer]

VastBufferPool manages 8 MiB buffers via indirect indexing.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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