package bufpool
import (
)
const (
minBitSize = 6
steps = 20
minSize = 1 << minBitSize
maxSize = 1 << (minBitSize + steps - 1)
maxPoolSize = maxSize << 1
defaultServePctile = 0.95
calibrateCallsThreshold = 42000
defaultSize = 4096
)
type Pool struct {
calls [steps]uint32
calibrating uint32
ServePctile float64
serveSize uint32
}
func ( *Pool) () int {
:= atomic.LoadUint32(&.serveSize)
if > 0 {
return int()
}
for := 0; < len(.calls); ++ {
:= atomic.LoadUint32(&.calls[])
if > 10 {
:= indexSize()
atomic.CompareAndSwapUint32(&.serveSize, 0, uint32())
return
}
}
return defaultSize
}
func ( *Pool) () *Buffer {
:= Get(.getServeSize())
.Reset()
return
}
func ( *Pool) () *Buffer {
return NewBuffer(make([]byte, 0, .getServeSize()))
}
func ( *Pool) ( *Buffer) {
:= .Len()
if == 0 {
= .Cap()
}
.UpdateLen()
Put()
}
func ( *Pool) ( int) {
:= index()
if atomic.AddUint32(&.calls[], 1) > calibrateCallsThreshold {
.calibrate()
}
}
func ( *Pool) () {
if !atomic.CompareAndSwapUint32(&.calibrating, 0, 1) {
return
}
var uint64
var [steps]uint32
for := 0; < len(.calls); ++ {
:= atomic.SwapUint32(&.calls[], 0)
[] =
+= uint64()
}
:= uint64(float64() * .getServePctile())
var int
= 0
for , := range & {
+= uint64()
if == 0 && >= {
= indexSize()
break
}
}
atomic.StoreUint32(&.serveSize, uint32())
atomic.StoreUint32(&.calibrating, 0)
}
func ( *Pool) () float64 {
if .ServePctile > 0 {
return .ServePctile
}
return defaultServePctile
}
func ( int) int {
if == 0 {
return 0
}
:= bits.Len32(uint32(( - 1) >> minBitSize))
if >= steps {
= steps - 1
}
return
}
func ( int) int {
:= index()
if == 0 || == indexSize() {
return
}
return - 1
}
func ( int) int {
return minSize << uint()
}