From ffd7357a1cb9df050f487dc541e9412fe6ea2672 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Fri, 8 May 2020 20:57:00 -0700 Subject: [PATCH] Calculate memory swap using the same memory overhead values as the hard cap; pterodactyl/panel#2000 --- server/environment_docker.go | 26 ++++++++++++-------------- server/server.go | 20 +++++++++++++++++++- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/server/environment_docker.go b/server/environment_docker.go index fdd4554..d4cf295 100644 --- a/server/environment_docker.go +++ b/server/environment_docker.go @@ -17,7 +17,6 @@ import ( "github.com/pterodactyl/wings/config" "go.uber.org/zap" "io" - "math" "os" "strconv" "strings" @@ -828,25 +827,24 @@ func (d *DockerEnvironment) exposedPorts() nat.PortSet { return out } + // Formats the resources available to a server instance in such as way that Docker will // generate a matching environment in the container. +// +// This will set the actual memory limit on the container using the multiplier which is the +// hard limit for the container (after which will result in a crash). We then set the +// reservation to be the expected memory limit based on simply multiplication. +// +// The swap value is either -1 to disable it, or set to the value of the hard memory limit +// plus the additional swap assigned to the server since Docker expects this value to be +// the same or higher than the memory limit. func (d *DockerEnvironment) getResourcesForServer() container.Resources { - overhead := 1.05 - // Set the hard limit for memory usage to be 5% more than the amount of memory assigned to - // the server. If the memory limit for the server is < 4G, use 10%, if less than 2G use - // 15%. This avoids unexpected crashes from processes like Java which run over the limit. - if d.Server.Build.MemoryLimit <= 2048 { - overhead = 1.15 - } else if d.Server.Build.MemoryLimit <= 4096 { - overhead = 1.10 - } - return container.Resources{ - Memory: int64(math.Round(float64(d.Server.Build.MemoryLimit) * 1000000.0 * overhead)), - MemoryReservation: d.Server.Build.MemoryLimit * 1000000, + Memory: d.Server.Build.BoundedMemoryLimit(), + MemoryReservation: d.Server.Build.MemoryLimit * 1_000_000, MemorySwap: d.Server.Build.ConvertedSwap(), CPUQuota: d.Server.Build.ConvertedCpuLimit(), - CPUPeriod: 100000, + CPUPeriod: 100_000, CPUShares: 1024, BlkioWeight: d.Server.Build.IoWeight, OomKillDisable: &d.Server.Container.OomDisabled, diff --git a/server/server.go b/server/server.go index 4c9e547..82deffe 100644 --- a/server/server.go +++ b/server/server.go @@ -9,6 +9,7 @@ import ( "github.com/pterodactyl/wings/config" "github.com/remeh/sizedwaitgroup" "go.uber.org/zap" + "math" "os" "strings" "sync" @@ -112,6 +113,23 @@ func (b *BuildSettings) ConvertedCpuLimit() int64 { return b.CpuLimit * 1000 } +// Set the hard limit for memory usage to be 5% more than the amount of memory assigned to +// the server. If the memory limit for the server is < 4G, use 10%, if less than 2G use +// 15%. This avoids unexpected crashes from processes like Java which run over the limit. +func (b *BuildSettings) MemoryOverheadMultiplier() float64 { + if b.MemoryLimit <= 2048 { + return 1.15 + } else if b.MemoryLimit <= 4096 { + return 1.10 + } + + return 1.05 +} + +func (b *BuildSettings) BoundedMemoryLimit() int64 { + return int64(math.Round(float64(b.MemoryLimit) * b.MemoryOverheadMultiplier() * 1_000_000)) +} + // Returns the amount of swap available as a total in bytes. This is returned as the amount // of memory available to the server initially, PLUS the amount of additional swap to include // which is the format used by Docker. @@ -120,7 +138,7 @@ func (b *BuildSettings) ConvertedSwap() int64 { return -1 } - return (b.Swap * 1000000) + (b.MemoryLimit * 1000000) + return (b.Swap * 1_000_000) + b.BoundedMemoryLimit() } // Defines the allocations available for a given server. When using the Docker environment