A sharded, generic object pool for Go with configurable growth and cleanup. It outperforms sync.Pool when objects are held longer between Get and Put, at the cost of extra overhead when retention is very short.
go get github.com/AlexsanderHamir/GenPool
pool.Fields[YourType] so it implements Poolable.NewPool or NewPoolWithConfig and call Get/Put.package main
import (
"github.com/AlexsanderHamir/GenPool/pool"
)
type Object struct {
Name string
Data []byte
pool.Fields[Object]
}
func main() {
allocator := func() *Object { return &Object{} }
cleaner := func(obj *Object) { obj.Name = ""; obj.Data = obj.Data[:0] }
p, err := pool.NewPool(allocator, cleaner)
if err != nil {
panic(err)
}
defer p.Close()
obj := p.Get()
obj.Name = "example"
obj.Data = append(obj.Data, 1, 2, 3)
p.Put(obj)
}
With custom cleanup and growth:
config := pool.Config[Object, *Object]{
Cleanup: pool.DefaultCleanupPolicy(pool.GcModerate),
Allocator: allocator,
Cleaner: cleaner,
Growth: pool.GrowthPolicy{
Enable: true,
MaxPoolSize: 1000,
},
}
p, err := pool.NewPoolWithConfig(config)
Config.NumShards (defaulting to runtime.GOMAXPROCS(0) at creation) and can be overridden with a positive value for testing or tuning.GrowthPolicy.Enable and MaxPoolSize, Get returns nil when the cap is reached.MinUsageCount. Disabled by default; enable via CleanupPolicy or DefaultCleanupPolicy(level).| Level | Interval | MinUsageCount | Use case |
|---|---|---|---|
GcDisable |
— | — | No automatic cleanup |
GcLow |
10m | 1 | High reuse, low churn |
GcModerate |
2m | 2 | Default balance |
GcAggressive |
30s | 3 | Memory-sensitive / bursty |
Cleanup: pool.DefaultCleanupPolicy(pool.GcModerate)
Or build a policy manually:
Cleanup: pool.CleanupPolicy{
Enabled: true,
Interval: 2 * time.Minute,
MinUsageCount: 2,
}
Limit pool size so Get returns nil when full:
Growth: pool.GrowthPolicy{
Enable: true,
MaxPoolSize: 5000,
}
If Enable is false, the pool has no size limit and relies on cleanup (if enabled) for reclaiming memory.
Benchmarks (darwin/arm64, Apple M1) show GenPool ahead when objects are held longer; sync.Pool can win when retention is very short.
go test -bench=. ./test/ (see test/pool_benchmark_test.go).Tip: Keep pool.Fields[Object] on its own cache line (e.g. add padding) to reduce false sharing under contention.
Disable automatic cleanup with GcDisable. You can then implement custom eviction by using the exported ShardedPool.Shards and each Shard's Head (and Single) to traverse or clear lists. The pool does not lock these; coordinate with Get/Put usage as needed.
go test ./... and go test -bench=. ./....git clone https://github.com/AlexsanderHamir/GenPool.git
cd GenPool
go test -v ./...
golangci-lint run # optional
MIT. See LICENSE.
$ claude mcp add GenPool \
-- python -m otcore.mcp_server <graph>