Documentation
¶
Overview ¶
Package pool creates a pool of your objects without additional wrapping and shards the linked list based on the number of available logical CPUs. This design improves performance under high concurrency and when there is significant work done between getting and returning objects.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrNoAllocator is returned when attempting to get an object but no allocator is configured. ErrNoAllocator = errors.New("no allocator configured") // ErrNoCleaner is returned when attempting to create a pool but no cleaner is configured. ErrNoCleaner = errors.New("no cleaner configured") )
Common errors that may be returned by the pool.
Functions ¶
This section is empty.
Types ¶
type Allocator ¶
type Allocator[T any] func() *T
Allocator is a function type that creates new objects for the pool.
type Cleaner ¶
type Cleaner[T any] func(*T)
Cleaner is a function type that cleans up objects before they are returned to the pool.
type CleanupPolicy ¶
type CleanupPolicy struct {
// Enabled determines if automatic cleanup is enabled.
Enabled bool
// Interval is how often the cleanup should run.
Interval time.Duration
// MinUsageCount is the number of usage BELOW which an object will be evicted.
MinUsageCount int64
}
CleanupPolicy defines how the pool should clean up unused objects.
func DefaultCleanupPolicy ¶
func DefaultCleanupPolicy(level GcLevel) CleanupPolicy
DefaultCleanupPolicy returns a default cleanup configuration based on specified level.
type Config ¶ added in v1.6.0
type Config[T any, P Poolable[T]] struct { // Cleanup defines the cleanup policy for the pool Cleanup CleanupPolicy // Growth defined the growth policy for the pool Growth GrowthPolicy // Allocator is the function to create new objects Allocator Allocator[T] // Cleaner is the function to clean objects before returning them to the pool Cleaner Cleaner[T] }
Config holds configuration options for the pool.
type Fields ¶ added in v1.6.0
type Fields[T any] struct { // contains filtered or unexported fields }
Fields provides intrusive fields and logic for poolable objects. By embedding this struct in your types, you avoid having to implement pooling logic separately for each pool.
func (*Fields[T]) GetNext ¶ added in v1.6.0
func (p *Fields[T]) GetNext() *T
GetNext implements interface function
func (*Fields[T]) GetShardIndex ¶ added in v1.6.6
GetShardIndex returns the shard index for this object
func (*Fields[T]) GetUsageCount ¶ added in v1.6.0
GetUsageCount implements interface function
func (*Fields[T]) IncrementUsage ¶ added in v1.6.0
func (p *Fields[T]) IncrementUsage()
IncrementUsage implements interface function
func (*Fields[T]) ResetUsage ¶ added in v1.6.0
func (p *Fields[T]) ResetUsage()
ResetUsage implements interface function
func (*Fields[T]) SetNext ¶ added in v1.6.0
func (p *Fields[T]) SetNext(n *T)
SetNext implements interface function
func (*Fields[T]) SetShardIndex ¶ added in v1.6.6
SetShardIndex sets the shard index for this object
type GcLevel ¶ added in v1.5.0
type GcLevel string
GcLevel offers different levels for clean up configuration. These presets control how aggressively GenPool reclaims memory. Note: Go's GC may still run unless you explicitly suppress it via debug.SetGCPercent(-1)
var ( // GcDisable disables GenPool's cleanup completely. // Objects will stay in the pool indefinitely unless manually cleared. GcDisable GcLevel = "disable" // GcLow performs cleanup at long intervals with minimal aggression. // Good for low-latency, high-reuse scenarios. GcLow GcLevel = "low" // GcModerate performs cleanup at regular intervals and evicts objects // that are lightly used. Balances reuse and memory usage. GcModerate GcLevel = "moderate" // GcAggressive enables frequent cleanup and removes objects // that are not reused often. Best for memory-constrained environments. GcAggressive GcLevel = "aggressive" )
type GrowthPolicy ¶ added in v1.6.1
type GrowthPolicy struct {
// MaxPoolSize defines the maximum number of objects the pool is allowed to grow to.
MaxPoolSize int64
// Enable activates growth control. If disabled, the pool will grow and shrink freely based on your configuration.
Enable bool
}
GrowthPolicy controls how the pool is allowed to grow. If unset, the pool will grow indefinitely, and any cleanup will rely solely on the CleanupPolicy.
type Poolable ¶
type Poolable[T any] interface { *T // GetNext returns the next object in the pool's linked list GetNext() *T // SetNext sets the next object in the pool's linked list SetNext(next *T) // GetUsageCount returns the number of times this object has been used GetUsageCount() int64 // IncrementUsage increments the usage count of this object IncrementUsage() // ResetUsage resets the usage count to 0 ResetUsage() // SetShardIndex sets the shard index for this object SetShardIndex(index int) // GetShardIndex returns the shard index for this object GetShardIndex() int }
Poolable is an interface that objects must implement to be stored in the pool.
type Shard ¶ added in v1.6.0
type Shard[T any, P Poolable[T]] struct { Head atomic.Pointer[T] // 8 bytes Single atomic.Pointer[T] // 8 bytes - fast path for single object Cond *sync.Cond // 8 bytes Mutex *sync.Mutex // 8 bytes // contains filtered or unexported fields }
Shard represents a single shard in the pool. It is 64 bytes in total to avoid false sharing across CPU cache lines.
type ShardedPool ¶ added in v1.4.0
type ShardedPool[T any, P Poolable[T]] struct { // shards is a slice of pool shards, each on its own cache line Shards []*Shard[T, P] // CurrentPoolLength changes at runtime, keeping track of how many uniqe objects have been created CurrentPoolLength atomic.Int64 // contains filtered or unexported fields }
ShardedPool is the main pool implementation using sharding for better concurrency.
func NewPool ¶
func NewPool[T any, P Poolable[T]](allocator Allocator[T], cleaner Cleaner[T]) (*ShardedPool[T, P], error)
NewPool creates a new sharded pool with the given configuration.
func NewPoolWithConfig ¶
func NewPoolWithConfig[T any, P Poolable[T]](cfg Config[T, P]) (*ShardedPool[T, P], error)
NewPoolWithConfig creates a new sharded pool with the specified configuration.
func (*ShardedPool[T, P]) Close ¶ added in v1.4.1
func (p *ShardedPool[T, P]) Close()
Close stops the cleanup goroutine and clears the pool.
func (*ShardedPool[T, P]) Get ¶ added in v1.5.5
func (p *ShardedPool[T, P]) Get() P
Get returns an object from the pool or creates a new one. Returns nil if MaxPoolSize is set, reached, and no reusable objects are available.
func (*ShardedPool[T, P]) GetBlock ¶ added in v1.6.3
func (p *ShardedPool[T, P]) GetBlock() P
GetBlock retrieves an object from the pool, blocking if necessary until one becomes available. It first attempts to reuse an object from the shard, then allocates a new one if the pool isn't full. If the pool has reached its maximum size, it blocks until another goroutine puts an object back.
func (*ShardedPool[T, P]) GetN ¶ added in v1.5.5
func (p *ShardedPool[T, P]) GetN(n int) []P
GetN returns N objects. This implementation creates memory, don't use it in the hot path, "make" always makes things much slower.
func (*ShardedPool[T, P]) Put ¶ added in v1.4.0
func (p *ShardedPool[T, P]) Put(obj P)
Put returns an object to the pool.
func (*ShardedPool[T, P]) PutBlock ¶ added in v1.6.3
func (p *ShardedPool[T, P]) PutBlock(obj P)
PutBlock returns an object to the pool and signals a blocked goroutine, if any. It attempts to atomically insert the object at the head of the most blocked shard's list. Only works if its returned within the same goroutine.
func (*ShardedPool[T, P]) PutN ¶ added in v1.5.5
func (p *ShardedPool[T, P]) PutN(objs []P)
PutN returns N objects.