mirror of
https://github.com/libp2p/go-libp2p-resource-manager.git
synced 2025-02-05 01:00:19 +08:00
refactor limit defaults for easy access and user manipulation
This commit is contained in:
parent
ddb39883f9
commit
575eadee04
104
limit.go
104
limit.go
@ -79,6 +79,13 @@ type BaseLimit struct {
|
||||
FD int
|
||||
}
|
||||
|
||||
// MemoryLimit is a mixin type for memory limits
|
||||
type MemoryLimit struct {
|
||||
MemoryFraction float64
|
||||
MinMemory int64
|
||||
MaxMemory int64
|
||||
}
|
||||
|
||||
func (l *BaseLimit) GetStreamLimit(dir network.Direction) int {
|
||||
if dir == network.DirInbound {
|
||||
return l.StreamsInbound
|
||||
@ -163,101 +170,12 @@ func (l *BasicLimiter) GetConnLimits() Limit {
|
||||
return l.ConnLimits
|
||||
}
|
||||
|
||||
// DefaultSystemBaseLimit returns the default BaseLimit for the System Scope.
|
||||
func DefaultSystemBaseLimit() BaseLimit {
|
||||
return BaseLimit{
|
||||
StreamsInbound: 4096,
|
||||
StreamsOutbound: 16384,
|
||||
Streams: 16384,
|
||||
ConnsInbound: 256,
|
||||
ConnsOutbound: 1024,
|
||||
Conns: 1024,
|
||||
FD: 512,
|
||||
}
|
||||
func (l *MemoryLimit) GetMemory(memoryCap int64) int64 {
|
||||
return memoryLimit(memoryCap, l.MemoryFraction, l.MinMemory, l.MaxMemory)
|
||||
}
|
||||
|
||||
// DefaultTransientBaseLimit returns the default BaseLimit for the Transient Scope.
|
||||
func DefaultTransientBaseLimit() BaseLimit {
|
||||
return BaseLimit{
|
||||
StreamsInbound: 128,
|
||||
StreamsOutbound: 512,
|
||||
Streams: 512,
|
||||
ConnsInbound: 32,
|
||||
ConnsOutbound: 128,
|
||||
Conns: 128,
|
||||
FD: 128,
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultServiceBaseLimit returns the default BaseLimit for Service Scopes.
|
||||
func DefaultServiceBaseLimit() BaseLimit {
|
||||
return BaseLimit{
|
||||
StreamsInbound: 2048,
|
||||
StreamsOutbound: 8192,
|
||||
Streams: 8192,
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultServicePeerBaseLimit returns the default BaseLimit per peer for Service Scopes.
|
||||
func DefaultServicePeerBaseLimit() BaseLimit {
|
||||
return BaseLimit{
|
||||
StreamsInbound: 256,
|
||||
StreamsOutbound: 512,
|
||||
Streams: 512,
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultProtocolBaseLimit returns the default BaseLimit for Protocol Scopes.
|
||||
func DefaultProtocolBaseLimit() BaseLimit {
|
||||
return BaseLimit{
|
||||
StreamsInbound: 1024,
|
||||
StreamsOutbound: 4096,
|
||||
Streams: 4096,
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultProtocolPeerBaseLimit returns the default BaseLimit per peer for Protocol Scopes.
|
||||
func DefaultProtocolPeerBaseLimit() BaseLimit {
|
||||
return BaseLimit{
|
||||
StreamsInbound: 128,
|
||||
StreamsOutbound: 256,
|
||||
Streams: 512,
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultPeerBaseLimit returns the default BaseLimit for Peer Scopes.
|
||||
func DefaultPeerBaseLimit() BaseLimit {
|
||||
return BaseLimit{
|
||||
StreamsInbound: 512,
|
||||
StreamsOutbound: 1024,
|
||||
Streams: 1024,
|
||||
ConnsInbound: 8,
|
||||
ConnsOutbound: 16,
|
||||
Conns: 16,
|
||||
FD: 8,
|
||||
}
|
||||
}
|
||||
|
||||
// ConnBaseLimit returns the BaseLimit for Connection Scopes.
|
||||
func ConnBaseLimit() BaseLimit {
|
||||
return BaseLimit{
|
||||
ConnsInbound: 1,
|
||||
ConnsOutbound: 1,
|
||||
Conns: 1,
|
||||
FD: 1,
|
||||
}
|
||||
}
|
||||
|
||||
// StreamBaseLimit returns the BaseLimit for Stream Scopes.
|
||||
func StreamBaseLimit() BaseLimit {
|
||||
return BaseLimit{
|
||||
StreamsInbound: 1,
|
||||
StreamsOutbound: 1,
|
||||
Streams: 1,
|
||||
}
|
||||
}
|
||||
|
||||
func memoryLimit(memoryCap int64, minMemory, maxMemory int64) int64 {
|
||||
func memoryLimit(memoryCap int64, memFraction float64, minMemory, maxMemory int64) int64 {
|
||||
memoryCap = int64(float64(memoryCap) * memFraction)
|
||||
switch {
|
||||
case memoryCap < minMemory:
|
||||
return minMemory
|
||||
|
113
limit_config.go
113
limit_config.go
@ -32,11 +32,11 @@ type limitConfig struct {
|
||||
FD int
|
||||
}
|
||||
|
||||
func (cfg *limitConfig) toLimit(base BaseLimit, memFraction float64, minMemory, maxMemory int64) (Limit, error) {
|
||||
func (cfg *limitConfig) toLimit(base BaseLimit, mem MemoryLimit) (Limit, error) {
|
||||
if cfg == nil {
|
||||
mem := memoryLimit(int64(float64(memory.TotalMemory())*memFraction), minMemory, maxMemory)
|
||||
m := mem.GetMemory(int64(memory.TotalMemory()))
|
||||
return &StaticLimit{
|
||||
Memory: mem,
|
||||
Memory: m,
|
||||
BaseLimit: base,
|
||||
}, nil
|
||||
}
|
||||
@ -75,20 +75,18 @@ func (cfg *limitConfig) toLimit(base BaseLimit, memFraction float64, minMemory,
|
||||
return nil, fmt.Errorf("negative memory fraction: %f", cfg.MemoryFraction)
|
||||
}
|
||||
if cfg.MemoryFraction > 0 {
|
||||
memFraction = cfg.MemoryFraction
|
||||
mem.MemoryFraction = cfg.MemoryFraction
|
||||
}
|
||||
if cfg.MinMemory > 0 {
|
||||
minMemory = cfg.MinMemory
|
||||
mem.MinMemory = cfg.MinMemory
|
||||
}
|
||||
if cfg.MaxMemory > 0 {
|
||||
maxMemory = cfg.MaxMemory
|
||||
mem.MaxMemory = cfg.MaxMemory
|
||||
}
|
||||
|
||||
return &DynamicLimit{
|
||||
MinMemory: minMemory,
|
||||
MaxMemory: maxMemory,
|
||||
MemoryFraction: memFraction,
|
||||
BaseLimit: base,
|
||||
MemoryLimit: mem,
|
||||
BaseLimit: base,
|
||||
}, nil
|
||||
|
||||
default:
|
||||
@ -96,16 +94,67 @@ func (cfg *limitConfig) toLimit(base BaseLimit, memFraction float64, minMemory,
|
||||
return nil, fmt.Errorf("negative memory fraction: %f", cfg.MemoryFraction)
|
||||
}
|
||||
if cfg.MemoryFraction > 0 {
|
||||
memFraction = cfg.MemoryFraction
|
||||
mem.MemoryFraction = cfg.MemoryFraction
|
||||
}
|
||||
if cfg.MinMemory > 0 {
|
||||
minMemory = cfg.MinMemory
|
||||
mem.MinMemory = cfg.MinMemory
|
||||
}
|
||||
if cfg.MaxMemory > 0 {
|
||||
maxMemory = cfg.MaxMemory
|
||||
mem.MaxMemory = cfg.MaxMemory
|
||||
}
|
||||
|
||||
mem := memoryLimit(int64(float64(memory.TotalMemory())*memFraction), minMemory, maxMemory)
|
||||
m := mem.GetMemory(int64(memory.TotalMemory()))
|
||||
return &StaticLimit{
|
||||
Memory: m,
|
||||
BaseLimit: base,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (cfg *limitConfig) toLimitFixed(base BaseLimit, mem int64) (Limit, error) {
|
||||
if cfg == nil {
|
||||
return &StaticLimit{
|
||||
Memory: mem,
|
||||
BaseLimit: base,
|
||||
}, nil
|
||||
}
|
||||
|
||||
if cfg.Streams > 0 {
|
||||
base.Streams = cfg.Streams
|
||||
}
|
||||
if cfg.StreamsInbound > 0 {
|
||||
base.StreamsInbound = cfg.StreamsInbound
|
||||
}
|
||||
if cfg.StreamsOutbound > 0 {
|
||||
base.StreamsOutbound = cfg.StreamsOutbound
|
||||
}
|
||||
if cfg.Conns > 0 {
|
||||
base.Conns = cfg.Conns
|
||||
}
|
||||
if cfg.ConnsInbound > 0 {
|
||||
base.ConnsInbound = cfg.ConnsInbound
|
||||
}
|
||||
if cfg.ConnsOutbound > 0 {
|
||||
base.ConnsOutbound = cfg.ConnsOutbound
|
||||
}
|
||||
if cfg.FD > 0 {
|
||||
base.FD = cfg.FD
|
||||
}
|
||||
|
||||
switch {
|
||||
case cfg.Memory > 0:
|
||||
return &StaticLimit{
|
||||
Memory: cfg.Memory,
|
||||
BaseLimit: base,
|
||||
}, nil
|
||||
|
||||
case cfg.Dynamic:
|
||||
return nil, fmt.Errorf("cannot specify dynamic limit for fixed memory limit")
|
||||
|
||||
default:
|
||||
if cfg.MemoryFraction > 0 || cfg.MinMemory > 0 || cfg.MaxMemory > 0 {
|
||||
return nil, fmt.Errorf("cannot specify dynamic range for fixed memory limit")
|
||||
}
|
||||
return &StaticLimit{
|
||||
Memory: mem,
|
||||
BaseLimit: base,
|
||||
@ -134,8 +183,14 @@ type limiterConfig struct {
|
||||
Stream *limitConfig
|
||||
}
|
||||
|
||||
// NewDefaultLimiterFromJSON creates a new limiter by parsing a json configuration,
|
||||
// using the default limits for fallback.
|
||||
func NewDefaultLimiterFromJSON(in io.Reader) (*BasicLimiter, error) {
|
||||
return NewLimiterFromJSON(in, DefaultLimits)
|
||||
}
|
||||
|
||||
// NewLimiterFromJSON creates a new limiter by parsing a json configuration.
|
||||
func NewLimiterFromJSON(in io.Reader) (*BasicLimiter, error) {
|
||||
func NewLimiterFromJSON(in io.Reader, defaults DefaultLimitConfig) (*BasicLimiter, error) {
|
||||
jin := json.NewDecoder(in)
|
||||
|
||||
var cfg limiterConfig
|
||||
@ -147,22 +202,22 @@ func NewLimiterFromJSON(in io.Reader) (*BasicLimiter, error) {
|
||||
limiter := new(BasicLimiter)
|
||||
var err error
|
||||
|
||||
limiter.SystemLimits, err = cfg.System.toLimit(DefaultSystemBaseLimit(), 0.125, 128<<20, 1<<30)
|
||||
limiter.SystemLimits, err = cfg.System.toLimit(defaults.SystemBaseLimit, defaults.SystemMemory)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid system limit: %w", err)
|
||||
}
|
||||
|
||||
limiter.TransientLimits, err = cfg.Transient.toLimit(DefaultTransientBaseLimit(), 0.0078125, 64<<20, 128<<20)
|
||||
limiter.TransientLimits, err = cfg.Transient.toLimit(defaults.TransientBaseLimit, defaults.TransientMemory)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid transient limit: %w", err)
|
||||
}
|
||||
|
||||
limiter.DefaultServiceLimits, err = cfg.ServiceDefault.toLimit(DefaultServiceBaseLimit(), 0.03125, 64<<20, 512<<20)
|
||||
limiter.DefaultServiceLimits, err = cfg.ServiceDefault.toLimit(defaults.ServiceBaseLimit, defaults.ServiceMemory)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invlaid default service limit: %w", err)
|
||||
}
|
||||
|
||||
limiter.DefaultServicePeerLimits, err = cfg.ServicePeerDefault.toLimit(DefaultServicePeerBaseLimit(), 0.0078125, 16<<20, 64<<20)
|
||||
limiter.DefaultServicePeerLimits, err = cfg.ServicePeerDefault.toLimit(defaults.ServicePeerBaseLimit, defaults.ServicePeerMemory)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invlaid default service peer limit: %w", err)
|
||||
}
|
||||
@ -170,7 +225,7 @@ func NewLimiterFromJSON(in io.Reader) (*BasicLimiter, error) {
|
||||
if len(cfg.Service) > 0 {
|
||||
limiter.ServiceLimits = make(map[string]Limit, len(cfg.Service))
|
||||
for svc, cfgLimit := range cfg.Service {
|
||||
limiter.ServiceLimits[svc], err = cfgLimit.toLimit(DefaultServiceBaseLimit(), 0.03125, 64<<20, 512<<20)
|
||||
limiter.ServiceLimits[svc], err = cfgLimit.toLimit(defaults.ServiceBaseLimit, defaults.ServiceMemory)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid service limit for %s: %w", svc, err)
|
||||
}
|
||||
@ -180,19 +235,19 @@ func NewLimiterFromJSON(in io.Reader) (*BasicLimiter, error) {
|
||||
if len(cfg.ServicePeer) > 0 {
|
||||
limiter.ServicePeerLimits = make(map[string]Limit, len(cfg.ServicePeer))
|
||||
for svc, cfgLimit := range cfg.ServicePeer {
|
||||
limiter.ServicePeerLimits[svc], err = cfgLimit.toLimit(DefaultServicePeerBaseLimit(), 0.0078125, 16<<20, 64<<20)
|
||||
limiter.ServicePeerLimits[svc], err = cfgLimit.toLimit(defaults.ServicePeerBaseLimit, defaults.ServicePeerMemory)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid service peer limit for %s: %w", svc, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
limiter.DefaultProtocolLimits, err = cfg.ProtocolDefault.toLimit(DefaultProtocolBaseLimit(), 0.0078125, 64<<20, 128<<20)
|
||||
limiter.DefaultProtocolLimits, err = cfg.ProtocolDefault.toLimit(defaults.ProtocolBaseLimit, defaults.ProtocolMemory)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invlaid default protocol limit: %w", err)
|
||||
}
|
||||
|
||||
limiter.DefaultProtocolPeerLimits, err = cfg.ProtocolPeerDefault.toLimit(DefaultProtocolPeerBaseLimit(), 0.0078125, 16<<20, 64<<20)
|
||||
limiter.DefaultProtocolPeerLimits, err = cfg.ProtocolPeerDefault.toLimit(defaults.ProtocolPeerBaseLimit, defaults.ProtocolPeerMemory)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invlaid default protocol peer limit: %w", err)
|
||||
}
|
||||
@ -200,7 +255,7 @@ func NewLimiterFromJSON(in io.Reader) (*BasicLimiter, error) {
|
||||
if len(cfg.Protocol) > 0 {
|
||||
limiter.ProtocolLimits = make(map[protocol.ID]Limit, len(cfg.Protocol))
|
||||
for p, cfgLimit := range cfg.Protocol {
|
||||
limiter.ProtocolLimits[protocol.ID(p)], err = cfgLimit.toLimit(DefaultProtocolBaseLimit(), 0.0078125, 64<<20, 128<<20)
|
||||
limiter.ProtocolLimits[protocol.ID(p)], err = cfgLimit.toLimit(defaults.ProtocolBaseLimit, defaults.ProtocolMemory)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid service limit for %s: %w", p, err)
|
||||
}
|
||||
@ -210,14 +265,14 @@ func NewLimiterFromJSON(in io.Reader) (*BasicLimiter, error) {
|
||||
if len(cfg.ProtocolPeer) > 0 {
|
||||
limiter.ProtocolPeerLimits = make(map[protocol.ID]Limit, len(cfg.ProtocolPeer))
|
||||
for p, cfgLimit := range cfg.ProtocolPeer {
|
||||
limiter.ProtocolPeerLimits[protocol.ID(p)], err = cfgLimit.toLimit(DefaultProtocolPeerBaseLimit(), 0.0078125, 16<<20, 64<<20)
|
||||
limiter.ProtocolPeerLimits[protocol.ID(p)], err = cfgLimit.toLimit(defaults.ProtocolPeerBaseLimit, defaults.ProtocolPeerMemory)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid service peer limit for %s: %w", p, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
limiter.DefaultPeerLimits, err = cfg.PeerDefault.toLimit(DefaultPeerBaseLimit(), 0.0078125, 64<<20, 1288<<20)
|
||||
limiter.DefaultPeerLimits, err = cfg.PeerDefault.toLimit(defaults.PeerBaseLimit, defaults.PeerMemory)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid peer limit: %w", err)
|
||||
}
|
||||
@ -229,19 +284,19 @@ func NewLimiterFromJSON(in io.Reader) (*BasicLimiter, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid peer ID %s: %w", p, err)
|
||||
}
|
||||
limiter.PeerLimits[pid], err = cfgLimit.toLimit(DefaultPeerBaseLimit(), 0.0078125, 64<<20, 1288<<20)
|
||||
limiter.PeerLimits[pid], err = cfgLimit.toLimit(defaults.PeerBaseLimit, defaults.PeerMemory)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid peer limit for %s: %w", p, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
limiter.ConnLimits, err = cfg.Conn.toLimit(ConnBaseLimit(), 1, 1<<20, 1<<20)
|
||||
limiter.ConnLimits, err = cfg.Conn.toLimitFixed(defaults.ConnBaseLimit, defaults.ConnMemory)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid conn limit: %w", err)
|
||||
}
|
||||
|
||||
limiter.StreamLimits, err = cfg.Stream.toLimit(StreamBaseLimit(), 1, 16<<20, 16<<20)
|
||||
limiter.StreamLimits, err = cfg.Stream.toLimitFixed(defaults.StreamBaseLimit, defaults.StreamMemory)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid stream limit: %w", err)
|
||||
}
|
||||
|
@ -12,14 +12,16 @@ func TestLimitConfigParser(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
defer in.Close()
|
||||
|
||||
limiter, err := NewLimiterFromJSON(in)
|
||||
limiter, err := NewDefaultLimiterFromJSON(in)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t,
|
||||
&DynamicLimit{
|
||||
MinMemory: 16384,
|
||||
MaxMemory: 65536,
|
||||
MemoryFraction: 0.125,
|
||||
MemoryLimit: MemoryLimit{
|
||||
MinMemory: 16384,
|
||||
MaxMemory: 65536,
|
||||
MemoryFraction: 0.125,
|
||||
},
|
||||
BaseLimit: BaseLimit{
|
||||
Streams: 64,
|
||||
StreamsInbound: 32,
|
||||
@ -35,21 +37,21 @@ func TestLimitConfigParser(t *testing.T) {
|
||||
require.Equal(t,
|
||||
&StaticLimit{
|
||||
Memory: 4096,
|
||||
BaseLimit: DefaultTransientBaseLimit(),
|
||||
BaseLimit: DefaultLimits.TransientBaseLimit,
|
||||
},
|
||||
limiter.TransientLimits)
|
||||
|
||||
require.Equal(t,
|
||||
&StaticLimit{
|
||||
Memory: 8192,
|
||||
BaseLimit: DefaultServiceBaseLimit(),
|
||||
BaseLimit: DefaultLimits.ServiceBaseLimit,
|
||||
},
|
||||
limiter.DefaultServiceLimits)
|
||||
|
||||
require.Equal(t,
|
||||
&StaticLimit{
|
||||
Memory: 2048,
|
||||
BaseLimit: DefaultServicePeerBaseLimit(),
|
||||
BaseLimit: DefaultLimits.ServicePeerBaseLimit,
|
||||
},
|
||||
limiter.DefaultServicePeerLimits)
|
||||
|
||||
@ -57,7 +59,7 @@ func TestLimitConfigParser(t *testing.T) {
|
||||
require.Equal(t,
|
||||
&StaticLimit{
|
||||
Memory: 8192,
|
||||
BaseLimit: DefaultServiceBaseLimit(),
|
||||
BaseLimit: DefaultLimits.ServiceBaseLimit,
|
||||
},
|
||||
limiter.ServiceLimits["A"])
|
||||
|
||||
@ -65,20 +67,20 @@ func TestLimitConfigParser(t *testing.T) {
|
||||
require.Equal(t,
|
||||
&StaticLimit{
|
||||
Memory: 4096,
|
||||
BaseLimit: DefaultServicePeerBaseLimit(),
|
||||
BaseLimit: DefaultLimits.ServicePeerBaseLimit,
|
||||
},
|
||||
limiter.ServicePeerLimits["A"])
|
||||
|
||||
require.Equal(t,
|
||||
&StaticLimit{
|
||||
Memory: 2048,
|
||||
BaseLimit: DefaultProtocolBaseLimit(),
|
||||
BaseLimit: DefaultLimits.ProtocolBaseLimit,
|
||||
},
|
||||
limiter.DefaultProtocolLimits)
|
||||
require.Equal(t,
|
||||
&StaticLimit{
|
||||
Memory: 1024,
|
||||
BaseLimit: DefaultProtocolPeerBaseLimit(),
|
||||
BaseLimit: DefaultLimits.ProtocolPeerBaseLimit,
|
||||
},
|
||||
limiter.DefaultProtocolPeerLimits)
|
||||
|
||||
@ -86,7 +88,7 @@ func TestLimitConfigParser(t *testing.T) {
|
||||
require.Equal(t,
|
||||
&StaticLimit{
|
||||
Memory: 8192,
|
||||
BaseLimit: DefaultProtocolBaseLimit(),
|
||||
BaseLimit: DefaultLimits.ProtocolBaseLimit,
|
||||
},
|
||||
limiter.ProtocolLimits["/A"])
|
||||
|
||||
@ -94,28 +96,28 @@ func TestLimitConfigParser(t *testing.T) {
|
||||
require.Equal(t,
|
||||
&StaticLimit{
|
||||
Memory: 4096,
|
||||
BaseLimit: DefaultProtocolPeerBaseLimit(),
|
||||
BaseLimit: DefaultLimits.ProtocolPeerBaseLimit,
|
||||
},
|
||||
limiter.ProtocolPeerLimits["/A"])
|
||||
|
||||
require.Equal(t,
|
||||
&StaticLimit{
|
||||
Memory: 4096,
|
||||
BaseLimit: DefaultPeerBaseLimit(),
|
||||
BaseLimit: DefaultLimits.PeerBaseLimit,
|
||||
},
|
||||
limiter.DefaultPeerLimits)
|
||||
|
||||
require.Equal(t,
|
||||
&StaticLimit{
|
||||
Memory: 1 << 20,
|
||||
BaseLimit: ConnBaseLimit(),
|
||||
BaseLimit: DefaultLimits.ConnBaseLimit,
|
||||
},
|
||||
limiter.ConnLimits)
|
||||
|
||||
require.Equal(t,
|
||||
&StaticLimit{
|
||||
Memory: 16 << 20,
|
||||
BaseLimit: StreamBaseLimit(),
|
||||
BaseLimit: DefaultLimits.StreamBaseLimit,
|
||||
},
|
||||
limiter.StreamLimits)
|
||||
|
||||
|
147
limit_defaults.go
Normal file
147
limit_defaults.go
Normal file
@ -0,0 +1,147 @@
|
||||
package rcmgr
|
||||
|
||||
// DefaultLimitConfig is a struct for configuring default limits.
|
||||
type DefaultLimitConfig struct {
|
||||
SystemBaseLimit BaseLimit
|
||||
SystemMemory MemoryLimit
|
||||
|
||||
TransientBaseLimit BaseLimit
|
||||
TransientMemory MemoryLimit
|
||||
|
||||
ServiceBaseLimit BaseLimit
|
||||
ServiceMemory MemoryLimit
|
||||
|
||||
ServicePeerBaseLimit BaseLimit
|
||||
ServicePeerMemory MemoryLimit
|
||||
|
||||
ProtocolBaseLimit BaseLimit
|
||||
ProtocolMemory MemoryLimit
|
||||
|
||||
ProtocolPeerBaseLimit BaseLimit
|
||||
ProtocolPeerMemory MemoryLimit
|
||||
|
||||
PeerBaseLimit BaseLimit
|
||||
PeerMemory MemoryLimit
|
||||
|
||||
ConnBaseLimit BaseLimit
|
||||
ConnMemory int64
|
||||
|
||||
StreamBaseLimit BaseLimit
|
||||
StreamMemory int64
|
||||
}
|
||||
|
||||
// DefaultLimits are the limits used by the default limiter constructors.
|
||||
var DefaultLimits = DefaultLimitConfig{
|
||||
SystemBaseLimit: BaseLimit{
|
||||
StreamsInbound: 4096,
|
||||
StreamsOutbound: 16384,
|
||||
Streams: 16384,
|
||||
ConnsInbound: 256,
|
||||
ConnsOutbound: 1024,
|
||||
Conns: 1024,
|
||||
FD: 512,
|
||||
},
|
||||
|
||||
SystemMemory: MemoryLimit{
|
||||
MemoryFraction: 0.125,
|
||||
MinMemory: 128 << 20,
|
||||
MaxMemory: 1 << 30,
|
||||
},
|
||||
|
||||
TransientBaseLimit: BaseLimit{
|
||||
StreamsInbound: 128,
|
||||
StreamsOutbound: 512,
|
||||
Streams: 512,
|
||||
ConnsInbound: 32,
|
||||
ConnsOutbound: 128,
|
||||
Conns: 128,
|
||||
FD: 128,
|
||||
},
|
||||
|
||||
TransientMemory: MemoryLimit{
|
||||
MemoryFraction: 1,
|
||||
MinMemory: 64 << 20,
|
||||
MaxMemory: 64 << 20,
|
||||
},
|
||||
|
||||
ServiceBaseLimit: BaseLimit{
|
||||
StreamsInbound: 2048,
|
||||
StreamsOutbound: 8192,
|
||||
Streams: 8192,
|
||||
},
|
||||
|
||||
ServiceMemory: MemoryLimit{
|
||||
MemoryFraction: 0.125 / 4,
|
||||
MinMemory: 64 << 20,
|
||||
MaxMemory: 256 << 20,
|
||||
},
|
||||
|
||||
ServicePeerBaseLimit: BaseLimit{
|
||||
StreamsInbound: 256,
|
||||
StreamsOutbound: 512,
|
||||
Streams: 512,
|
||||
},
|
||||
|
||||
ServicePeerMemory: MemoryLimit{
|
||||
MemoryFraction: 0.125 / 16,
|
||||
MinMemory: 16 << 20,
|
||||
MaxMemory: 64 << 20,
|
||||
},
|
||||
|
||||
ProtocolBaseLimit: BaseLimit{
|
||||
StreamsInbound: 1024,
|
||||
StreamsOutbound: 4096,
|
||||
Streams: 4096,
|
||||
},
|
||||
|
||||
ProtocolMemory: MemoryLimit{
|
||||
MemoryFraction: 0.125 / 8,
|
||||
MinMemory: 64 << 20,
|
||||
MaxMemory: 128 << 20,
|
||||
},
|
||||
|
||||
ProtocolPeerBaseLimit: BaseLimit{
|
||||
StreamsInbound: 128,
|
||||
StreamsOutbound: 256,
|
||||
Streams: 512,
|
||||
},
|
||||
|
||||
ProtocolPeerMemory: MemoryLimit{
|
||||
MemoryFraction: 0.125 / 16,
|
||||
MinMemory: 16 << 20,
|
||||
MaxMemory: 64 << 20,
|
||||
},
|
||||
|
||||
PeerBaseLimit: BaseLimit{
|
||||
StreamsInbound: 512,
|
||||
StreamsOutbound: 1024,
|
||||
Streams: 1024,
|
||||
ConnsInbound: 8,
|
||||
ConnsOutbound: 16,
|
||||
Conns: 16,
|
||||
FD: 8,
|
||||
},
|
||||
|
||||
PeerMemory: MemoryLimit{
|
||||
MemoryFraction: 0.125 / 16,
|
||||
MinMemory: 64 << 20,
|
||||
MaxMemory: 128 << 20,
|
||||
},
|
||||
|
||||
ConnBaseLimit: BaseLimit{
|
||||
ConnsInbound: 1,
|
||||
ConnsOutbound: 1,
|
||||
Conns: 1,
|
||||
FD: 1,
|
||||
},
|
||||
|
||||
ConnMemory: 1 << 20,
|
||||
|
||||
StreamBaseLimit: BaseLimit{
|
||||
StreamsInbound: 1,
|
||||
StreamsOutbound: 1,
|
||||
Streams: 1,
|
||||
},
|
||||
|
||||
StreamMemory: 16 << 20,
|
||||
}
|
@ -9,14 +9,7 @@ import (
|
||||
// DynamicLimit is a limit with dynamic memory values, based on available (free) memory
|
||||
type DynamicLimit struct {
|
||||
BaseLimit
|
||||
|
||||
// MinMemory is the minimum memory for this limit
|
||||
MinMemory int64
|
||||
// MaxMemory is the maximum memory for this limit
|
||||
MaxMemory int64
|
||||
// MemoryFraction is the fraction of available memory allowed for this limit,
|
||||
// bounded by [MinMemory, MaxMemory]
|
||||
MemoryFraction float64
|
||||
MemoryLimit
|
||||
}
|
||||
|
||||
var _ Limit = (*DynamicLimit)(nil)
|
||||
@ -31,18 +24,16 @@ func (l *DynamicLimit) GetMemoryLimit() int64 {
|
||||
runtime.ReadMemStats(&memstat)
|
||||
|
||||
freemem += (memstat.HeapInuse - memstat.HeapAlloc) + (memstat.HeapIdle - memstat.HeapReleased)
|
||||
|
||||
limit := int64(float64(freemem) * l.MemoryFraction)
|
||||
return memoryLimit(limit, l.MinMemory, l.MaxMemory)
|
||||
return l.MemoryLimit.GetMemory(int64(freemem))
|
||||
}
|
||||
|
||||
func (l *DynamicLimit) WithMemoryLimit(memFraction float64, minMemory, maxMemory int64) Limit {
|
||||
r := new(DynamicLimit)
|
||||
*r = *l
|
||||
|
||||
r.MemoryFraction *= memFraction
|
||||
r.MinMemory = minMemory
|
||||
r.MaxMemory = maxMemory
|
||||
r.MemoryLimit.MemoryFraction *= memFraction
|
||||
r.MemoryLimit.MinMemory = minMemory
|
||||
r.MemoryLimit.MaxMemory = maxMemory
|
||||
|
||||
return r
|
||||
}
|
||||
@ -78,61 +69,49 @@ func (l *DynamicLimit) WithFDLimit(numFD int) Limit {
|
||||
return r
|
||||
}
|
||||
|
||||
// NewDynamicLimiter creates a limiter with default limits and a memory cap dynamically computed
|
||||
// based on available memory. minMemory and maxMemory specify the system memory bounds,
|
||||
// while memFraction specifies the fraction of available memory available for the system, within
|
||||
// the specified bounds.
|
||||
func NewDynamicLimiter(memFraction float64, minMemory, maxMemory int64) *BasicLimiter {
|
||||
// NewDefaultDynamicLimiter creates a limiter with default limits and a memory cap
|
||||
// dynamically computed based on available memory.
|
||||
func NewDefaultDynamicLimiter() *BasicLimiter {
|
||||
return NewDynamicLimiter(DefaultLimits)
|
||||
}
|
||||
|
||||
// NewDynamicLimiter crates a dynamic limiter with the specified defaults
|
||||
func NewDynamicLimiter(cfg DefaultLimitConfig) *BasicLimiter {
|
||||
system := &DynamicLimit{
|
||||
MinMemory: minMemory,
|
||||
MaxMemory: maxMemory,
|
||||
MemoryFraction: memFraction,
|
||||
BaseLimit: DefaultSystemBaseLimit(),
|
||||
MemoryLimit: cfg.SystemMemory,
|
||||
BaseLimit: cfg.SystemBaseLimit,
|
||||
}
|
||||
transient := &DynamicLimit{
|
||||
MinMemory: 64 << 20,
|
||||
MaxMemory: 128 << 20,
|
||||
MemoryFraction: memFraction / 16,
|
||||
BaseLimit: DefaultTransientBaseLimit(),
|
||||
MemoryLimit: cfg.TransientMemory,
|
||||
BaseLimit: cfg.TransientBaseLimit,
|
||||
}
|
||||
svc := &DynamicLimit{
|
||||
MinMemory: 64 << 20,
|
||||
MaxMemory: 512 << 20,
|
||||
MemoryFraction: memFraction / 4,
|
||||
BaseLimit: DefaultServiceBaseLimit(),
|
||||
MemoryLimit: cfg.ServiceMemory,
|
||||
BaseLimit: cfg.ServiceBaseLimit,
|
||||
}
|
||||
svcPeer := &DynamicLimit{
|
||||
MinMemory: 16 << 20,
|
||||
MaxMemory: 64 << 20,
|
||||
MemoryFraction: memFraction / 16,
|
||||
BaseLimit: DefaultServicePeerBaseLimit(),
|
||||
MemoryLimit: cfg.ServicePeerMemory,
|
||||
BaseLimit: cfg.ServicePeerBaseLimit,
|
||||
}
|
||||
proto := &DynamicLimit{
|
||||
MinMemory: 64 << 20,
|
||||
MaxMemory: 128 << 20,
|
||||
MemoryFraction: memFraction / 16,
|
||||
BaseLimit: DefaultProtocolBaseLimit(),
|
||||
MemoryLimit: cfg.ProtocolMemory,
|
||||
BaseLimit: cfg.ProtocolBaseLimit,
|
||||
}
|
||||
protoPeer := &DynamicLimit{
|
||||
MinMemory: 16 << 20,
|
||||
MaxMemory: 64 << 20,
|
||||
MemoryFraction: memFraction / 16,
|
||||
BaseLimit: DefaultProtocolPeerBaseLimit(),
|
||||
MemoryLimit: cfg.ProtocolPeerMemory,
|
||||
BaseLimit: cfg.ProtocolPeerBaseLimit,
|
||||
}
|
||||
|
||||
peer := &DynamicLimit{
|
||||
MinMemory: 64 << 20,
|
||||
MaxMemory: 128 << 20,
|
||||
MemoryFraction: memFraction / 16,
|
||||
BaseLimit: DefaultPeerBaseLimit(),
|
||||
MemoryLimit: cfg.PeerMemory,
|
||||
BaseLimit: cfg.PeerBaseLimit,
|
||||
}
|
||||
conn := &StaticLimit{
|
||||
Memory: 1 << 20,
|
||||
BaseLimit: ConnBaseLimit(),
|
||||
Memory: cfg.ConnMemory,
|
||||
BaseLimit: cfg.ConnBaseLimit,
|
||||
}
|
||||
stream := &StaticLimit{
|
||||
Memory: 16 << 20,
|
||||
BaseLimit: StreamBaseLimit(),
|
||||
Memory: cfg.StreamMemory,
|
||||
BaseLimit: cfg.StreamBaseLimit,
|
||||
}
|
||||
|
||||
return &BasicLimiter{
|
||||
|
@ -61,55 +61,67 @@ func (l *StaticLimit) WithFDLimit(numFD int) Limit {
|
||||
return r
|
||||
}
|
||||
|
||||
// NewStaticLimiter creates a limiter with default base limits and a system memory cap specified as
|
||||
// a fraction of total system memory. The assigned memory will not be less than minMemory or more
|
||||
// than maxMemory.
|
||||
func NewStaticLimiter(memFraction float64, minMemory, maxMemory int64) *BasicLimiter {
|
||||
memoryCap := memoryLimit(int64(float64(memory.TotalMemory())*memFraction), minMemory, maxMemory)
|
||||
return newDefaultStaticLimiter(memoryCap)
|
||||
// NewDefaultStaticLimiter creates a static limiter with default base limits and a system memory cap
|
||||
// specified as a fraction of total system memory. The assigned memory will not be less than
|
||||
// minMemory or more than maxMemory.
|
||||
func NewDefaultStaticLimiter(memFraction float64, minMemory, maxMemory int64) *BasicLimiter {
|
||||
memoryCap := memoryLimit(int64(memory.TotalMemory()), memFraction, minMemory, maxMemory)
|
||||
return NewStaticLimiter(memoryCap, DefaultLimits)
|
||||
}
|
||||
|
||||
// NewFixedLimiter creates a limiter with default base limits and a specified system memory cap.
|
||||
func NewFixedLimiter(memoryCap int64) *BasicLimiter {
|
||||
return newDefaultStaticLimiter(memoryCap)
|
||||
// NewDefaultFixedLimiter creates a static limiter with default base limits and a specified system
|
||||
// memory cap.
|
||||
func NewDefaultFixedLimiter(memoryCap int64) *BasicLimiter {
|
||||
return NewStaticLimiter(memoryCap, DefaultLimits)
|
||||
}
|
||||
|
||||
func newDefaultStaticLimiter(memoryCap int64) *BasicLimiter {
|
||||
// NewDefaultLimiter creates a static limiter with the default limits
|
||||
func NewDefaultLimiter() *BasicLimiter {
|
||||
return NewDefaultStaticLimiter(
|
||||
DefaultLimits.SystemMemory.MemoryFraction,
|
||||
DefaultLimits.SystemMemory.MinMemory,
|
||||
DefaultLimits.SystemMemory.MaxMemory,
|
||||
)
|
||||
}
|
||||
|
||||
// NewStaticLimiter creates a static limiter using the specified system memory cap and default
|
||||
// limit config.
|
||||
func NewStaticLimiter(memoryCap int64, cfg DefaultLimitConfig) *BasicLimiter {
|
||||
system := &StaticLimit{
|
||||
Memory: memoryCap,
|
||||
BaseLimit: DefaultSystemBaseLimit(),
|
||||
BaseLimit: cfg.SystemBaseLimit,
|
||||
}
|
||||
transient := &StaticLimit{
|
||||
Memory: memoryLimit(memoryCap/16, 64<<20, 128<<20),
|
||||
BaseLimit: DefaultTransientBaseLimit(),
|
||||
Memory: cfg.SystemMemory.GetMemory(memoryCap),
|
||||
BaseLimit: cfg.TransientBaseLimit,
|
||||
}
|
||||
svc := &StaticLimit{
|
||||
Memory: memoryLimit(memoryCap/4, 64<<20, 512<<20),
|
||||
BaseLimit: DefaultServiceBaseLimit(),
|
||||
Memory: cfg.ServiceMemory.GetMemory(memoryCap),
|
||||
BaseLimit: cfg.ServiceBaseLimit,
|
||||
}
|
||||
svcPeer := &StaticLimit{
|
||||
Memory: memoryLimit(memoryCap/16, 16<<20, 64<<20),
|
||||
BaseLimit: DefaultServicePeerBaseLimit(),
|
||||
Memory: cfg.ServicePeerMemory.GetMemory(memoryCap),
|
||||
BaseLimit: cfg.ServicePeerBaseLimit,
|
||||
}
|
||||
proto := &StaticLimit{
|
||||
Memory: memoryLimit(memoryCap/16, 64<<20, 128<<20),
|
||||
BaseLimit: DefaultProtocolBaseLimit(),
|
||||
Memory: cfg.ProtocolMemory.GetMemory(memoryCap),
|
||||
BaseLimit: cfg.ProtocolBaseLimit,
|
||||
}
|
||||
protoPeer := &StaticLimit{
|
||||
Memory: memoryLimit(memoryCap/16, 16<<20, 64<<20),
|
||||
BaseLimit: DefaultProtocolPeerBaseLimit(),
|
||||
Memory: cfg.ProtocolPeerMemory.GetMemory(memoryCap),
|
||||
BaseLimit: cfg.ProtocolPeerBaseLimit,
|
||||
}
|
||||
peer := &StaticLimit{
|
||||
Memory: memoryLimit(memoryCap/16, 64<<20, 128<<20),
|
||||
BaseLimit: DefaultPeerBaseLimit(),
|
||||
Memory: cfg.PeerMemory.GetMemory(memoryCap),
|
||||
BaseLimit: cfg.PeerBaseLimit,
|
||||
}
|
||||
conn := &StaticLimit{
|
||||
Memory: 1 << 20,
|
||||
BaseLimit: ConnBaseLimit(),
|
||||
Memory: cfg.ConnMemory,
|
||||
BaseLimit: cfg.ConnBaseLimit,
|
||||
}
|
||||
stream := &StaticLimit{
|
||||
Memory: 16 << 20,
|
||||
BaseLimit: StreamBaseLimit(),
|
||||
Memory: cfg.StreamMemory,
|
||||
BaseLimit: cfg.StreamBaseLimit,
|
||||
}
|
||||
|
||||
return &BasicLimiter{
|
||||
|
Loading…
Reference in New Issue
Block a user