129 lines
3.3 KiB
Go
129 lines
3.3 KiB
Go
|
package rcmgr
|
||
|
|
||
|
import (
|
||
|
"runtime"
|
||
|
|
||
|
"github.com/pbnjay/memory"
|
||
|
)
|
||
|
|
||
|
// DynamicLimit is a limit with dynamic memory values, based on available (free) memory
|
||
|
type DynamicLimit struct {
|
||
|
BaseLimit
|
||
|
MemoryLimit
|
||
|
}
|
||
|
|
||
|
var _ Limit = (*DynamicLimit)(nil)
|
||
|
|
||
|
func (l *DynamicLimit) GetMemoryLimit() int64 {
|
||
|
freemem := memory.FreeMemory()
|
||
|
|
||
|
// account for memory retained by the runtime that is actually free
|
||
|
// HeapInuse - HeapAlloc is the memory available in allocator spans
|
||
|
// HeapIdle - HeapReleased is memory held by the runtime that could be returned to the OS
|
||
|
var memstat runtime.MemStats
|
||
|
runtime.ReadMemStats(&memstat)
|
||
|
|
||
|
freemem += (memstat.HeapInuse - memstat.HeapAlloc) + (memstat.HeapIdle - memstat.HeapReleased)
|
||
|
return l.MemoryLimit.GetMemory(int64(freemem))
|
||
|
}
|
||
|
|
||
|
func (l *DynamicLimit) WithMemoryLimit(memFraction float64, minMemory, maxMemory int64) Limit {
|
||
|
r := new(DynamicLimit)
|
||
|
*r = *l
|
||
|
|
||
|
r.MemoryLimit.MemoryFraction *= memFraction
|
||
|
r.MemoryLimit.MinMemory = minMemory
|
||
|
r.MemoryLimit.MaxMemory = maxMemory
|
||
|
|
||
|
return r
|
||
|
}
|
||
|
|
||
|
func (l *DynamicLimit) WithStreamLimit(numStreamsIn, numStreamsOut, numStreams int) Limit {
|
||
|
r := new(DynamicLimit)
|
||
|
*r = *l
|
||
|
|
||
|
r.BaseLimit.StreamsInbound = numStreamsIn
|
||
|
r.BaseLimit.StreamsOutbound = numStreamsOut
|
||
|
r.BaseLimit.Streams = numStreams
|
||
|
|
||
|
return r
|
||
|
}
|
||
|
|
||
|
func (l *DynamicLimit) WithConnLimit(numConnsIn, numConnsOut, numConns int) Limit {
|
||
|
r := new(DynamicLimit)
|
||
|
*r = *l
|
||
|
|
||
|
r.BaseLimit.ConnsInbound = numConnsIn
|
||
|
r.BaseLimit.ConnsOutbound = numConnsOut
|
||
|
r.BaseLimit.Conns = numConns
|
||
|
|
||
|
return r
|
||
|
}
|
||
|
|
||
|
func (l *DynamicLimit) WithFDLimit(numFD int) Limit {
|
||
|
r := new(DynamicLimit)
|
||
|
*r = *l
|
||
|
|
||
|
r.BaseLimit.FD = numFD
|
||
|
|
||
|
return r
|
||
|
}
|
||
|
|
||
|
// NewDefaultDynamicLimiter creates a limiter with default limits and a memory cap
|
||
|
// dynamically computed based on available memory.
|
||
|
func NewDefaultDynamicLimiter(memFraction float64, minMemory, maxMemory int64) *BasicLimiter {
|
||
|
return NewDynamicLimiter(DefaultLimits.WithSystemMemory(memFraction, minMemory, maxMemory))
|
||
|
}
|
||
|
|
||
|
// NewDynamicLimiter crates a dynamic limiter with the specified defaults
|
||
|
func NewDynamicLimiter(cfg DefaultLimitConfig) *BasicLimiter {
|
||
|
system := &DynamicLimit{
|
||
|
MemoryLimit: cfg.SystemMemory,
|
||
|
BaseLimit: cfg.SystemBaseLimit,
|
||
|
}
|
||
|
transient := &DynamicLimit{
|
||
|
MemoryLimit: cfg.TransientMemory,
|
||
|
BaseLimit: cfg.TransientBaseLimit,
|
||
|
}
|
||
|
svc := &DynamicLimit{
|
||
|
MemoryLimit: cfg.ServiceMemory,
|
||
|
BaseLimit: cfg.ServiceBaseLimit,
|
||
|
}
|
||
|
svcPeer := &DynamicLimit{
|
||
|
MemoryLimit: cfg.ServicePeerMemory,
|
||
|
BaseLimit: cfg.ServicePeerBaseLimit,
|
||
|
}
|
||
|
proto := &DynamicLimit{
|
||
|
MemoryLimit: cfg.ProtocolMemory,
|
||
|
BaseLimit: cfg.ProtocolBaseLimit,
|
||
|
}
|
||
|
protoPeer := &DynamicLimit{
|
||
|
MemoryLimit: cfg.ProtocolPeerMemory,
|
||
|
BaseLimit: cfg.ProtocolPeerBaseLimit,
|
||
|
}
|
||
|
peer := &DynamicLimit{
|
||
|
MemoryLimit: cfg.PeerMemory,
|
||
|
BaseLimit: cfg.PeerBaseLimit,
|
||
|
}
|
||
|
conn := &StaticLimit{
|
||
|
Memory: cfg.ConnMemory,
|
||
|
BaseLimit: cfg.ConnBaseLimit,
|
||
|
}
|
||
|
stream := &StaticLimit{
|
||
|
Memory: cfg.StreamMemory,
|
||
|
BaseLimit: cfg.StreamBaseLimit,
|
||
|
}
|
||
|
|
||
|
return &BasicLimiter{
|
||
|
SystemLimits: system,
|
||
|
TransientLimits: transient,
|
||
|
DefaultServiceLimits: svc,
|
||
|
DefaultServicePeerLimits: svcPeer,
|
||
|
DefaultProtocolLimits: proto,
|
||
|
DefaultProtocolPeerLimits: protoPeer,
|
||
|
DefaultPeerLimits: peer,
|
||
|
ConnLimits: conn,
|
||
|
StreamLimits: stream,
|
||
|
}
|
||
|
}
|