https://github.com/koykov/lbpool
Pool based on leaky buffer template.
https://github.com/koykov/lbpool
leaky-buffer pool
Last synced: about 1 month ago
JSON representation
Pool based on leaky buffer template.
- Host: GitHub
- URL: https://github.com/koykov/lbpool
- Owner: koykov
- License: mit
- Created: 2020-01-16T21:36:14.000Z (about 6 years ago)
- Default Branch: master
- Last Pushed: 2023-04-23T19:32:19.000Z (almost 3 years ago)
- Last Synced: 2025-09-01T12:51:09.933Z (7 months ago)
- Topics: leaky-buffer, pool
- Language: Go
- Homepage:
- Size: 18.6 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: readme.md
- License: license.md
Awesome Lists containing this project
README
# Leaky Buffer Pool
An implementation of `Pool` based on the [leaky buffer](https://golang.org/doc/effective_go.html#leaky_buffer) pattern.
Actually, this pattern is more accurately called [leaky bucket](https://en.wikipedia.org/wiki/Leaky_bucket), but in Go terminology,
this specific name is used.
This solution has both advantages and disadvantages in comparison to native [sync.Pool](https://golang.org/src/sync/pool.go) implementation:
the native solution is faster, but it has a significant drawback:
> Any item stored in the Pool may be removed automatically at any time without
notification. If the Pool holds the only reference when this happens, the
item might be deallocated.
> - https://golang.org/src/sync/pool.go
If you need to store something in the pool that cannot be automatically cleaned up by the GC, you will encounter a memory leak.
Such objects include, for example, [cbyte](https://github.com/koykov/cbyte) arenas, which require manual release.
Outside of this feature, this pool works similarly to the native one.
## API
The `Get` method of the pool is full analogue to the native pool's method and has the same signature:
```go
func Get() any
```
The `Put` method can only accept objects that implement the `Releaser` interface:
```go
type Releaser interface {
Release()
}
func Put(x Releaser) bool
```
It also returns a `bool` indicating whether the object leaked past the bucket or not.
The pool requires initialization via the `New` constructor:
```go
func New(size uint, releaseFactor float64, options ...Option) Pool
```
with arguments:
* `size` - The maximum size of the pool. Once this size is reached, all newly arriving elements will leak.
* `releaseFactor` - The proportion of incoming elements that will be forcibly leaked past the pool. This is needed for gradual renewal of elements in the pool.
* `options` - A list of optional functions that allow setting additional pool parameters.
Currently, three optional functions are available:
* `WithNewFn` - Sets the New function for constructing an object to return instead of a `nil` value.
* `WithShards` - The number of pool shards, needed to reduce lock contention on the internal channel's mutex.
* `WithSampler` - Sets the sampler ti evaluate should item stored to the pool or not. May be helpful to refresh pool.
* `WithMetricsWriter` - Connects a component for writing metrics to the pool.
## Usage
```go
import (
"github.com/koykov/lbpool"
"github.com/koykov/lbpool/metrics/victoria"
)
const (
poolSize = 100 // max pool size
releaseFactor = .05 // part of items that will leak independent of leaky logic
)
type item struct{...}
func (item) Release() {...}
var pool = lbpool.New(poolSize, releaseFactor, lbpool.WithNewFn(func() any { return &item{} }),
lbpool.WithMetricsWriter(victoria.NewWriter("my_pool")))
itm := pool.Get().(*item)
...
pool.Put(itm)
```
## Performance
The pool is implemented over Go channels and works several times slower than the native pool:
```
BenchmarkPool-8 23870334 50.07 ns/op 0 B/op 0 allocs/op
BenchmarkPoolParallel-8 100000000 11.62 ns/op 0 B/op 0 allocs/op
BenchmarkPoolNative-8 100000000 10.59 ns/op 0 B/op 0 allocs/op
BenchmarkPoolNativeParallel-8 424538383 2.920 ns/op 0 B/op 0 allocs/op
```
Consider this when choosing tools for your tasks.