fn: MaxTotalCPU and MaxTotalMemory in non-Linux systems (#1043)

Non-Linux systems skip some of memory/cpu determination
code in resource tracker. But config settings to cap
these are used in tests, so they must not be ignored.

With this change, we apply these config settings even
on non-Linux systems.

Memory allocation code is also now same in non-Linux
systems, but default is raised to 2GB from 1.5GB.
This commit is contained in:
Tolga Ceylan
2018-06-06 14:50:21 -07:00
committed by GitHub
parent 6ea13d0f6d
commit 4fcb52f69d

View File

@@ -21,6 +21,9 @@ import (
const (
Mem1MB = 1024 * 1024
Mem1GB = 1024 * 1024 * 1024
// Assume 2GB RAM on non-linux systems
DefaultNonLinuxMemory = 2048 * Mem1MB
)
var CapacityFull = errors.New("max capacity reached")
@@ -357,7 +360,12 @@ func clampUint64(val, min, max uint64) uint64 {
func (a *resourceTracker) initializeCPU(cfg *AgentConfig) {
var maxSyncCPU, maxAsyncCPU, cpuAsyncHWMark uint64
var totalCPU, availCPU uint64
// Use all available CPU from go.runtime in non-linux systems. We ignore
// non-linux container implementations and their limits on CPU if there's any.
// (This is also the default if we cannot determine limits from proc or sysfs)
totalCPU := uint64(runtime.NumCPU() * 1000)
availCPU := totalCPU
if runtime.GOOS == "linux" {
@@ -367,30 +375,26 @@ func (a *resourceTracker) initializeCPU(cfg *AgentConfig) {
numCPU, err := checkProcCPU()
if err != nil {
logrus.WithError(err).Error("Error checking for CPU, falling back to runtime CPU count.")
numCPU = uint64(runtime.NumCPU())
} else {
totalCPU = 1000 * numCPU
availCPU = totalCPU
}
totalCPU = 1000 * numCPU
availCPU = totalCPU
// Clamp further if cgroups CFS quota/period limits are in place
cgroupCPU := checkCgroupCPU()
if cgroupCPU > 0 {
availCPU = minUint64(availCPU, cgroupCPU)
}
// now based on cfg, further clamp on calculated values
if cfg != nil && cfg.MaxTotalCPU != 0 {
availCPU = minUint64(cfg.MaxTotalCPU, availCPU)
}
// TODO: check cgroup cpuset to clamp this further. We might be restricted into
// a subset of CPUs. (eg. /sys/fs/cgroup/cpuset/cpuset.effective_cpus)
// TODO: skip CPU headroom for ourselves for now
} else {
totalCPU = uint64(runtime.NumCPU() * 1000)
availCPU = totalCPU
}
// now based on cfg, further clamp on calculated values
if cfg != nil && cfg.MaxTotalCPU != 0 {
availCPU = minUint64(cfg.MaxTotalCPU, availCPU)
}
logrus.WithFields(logrus.Fields{
@@ -428,6 +432,8 @@ func (a *resourceTracker) initializeMemory(cfg *AgentConfig) {
var maxSyncMemory, maxAsyncMemory, ramAsyncHWMark uint64
availMemory := uint64(DefaultNonLinuxMemory)
if runtime.GOOS == "linux" {
// system wide available memory
@@ -436,7 +442,7 @@ func (a *resourceTracker) initializeMemory(cfg *AgentConfig) {
logrus.WithError(err).Fatal("Cannot get the proper memory information to size server.")
}
availMemory := totalMemory
availMemory = totalMemory
// cgroup limit restriction on memory usage
cGroupLimit, err := checkCgroupMem()
@@ -453,32 +459,26 @@ func (a *resourceTracker) initializeMemory(cfg *AgentConfig) {
}
availMemory = availMemory - headRoom
// now based on cfg, further clamp on calculated values
if cfg != nil && cfg.MaxTotalMemory != 0 {
availMemory = minUint64(cfg.MaxTotalMemory, availMemory)
}
logrus.WithFields(logrus.Fields{
"totalMemory": totalMemory,
"availMemory": availMemory,
"headRoom": headRoom,
"cgroupLimit": cGroupLimit,
}).Info("available memory")
// %20 of ram for sync only reserve
maxSyncMemory = uint64(availMemory * 2 / 10)
maxAsyncMemory = availMemory - maxSyncMemory
ramAsyncHWMark = maxAsyncMemory * 8 / 10
} else {
// non-linux: assume 512MB sync only memory and 1.5GB async + sync memory
maxSyncMemory = 512 * Mem1MB
maxAsyncMemory = (1024 + 512) * Mem1MB
ramAsyncHWMark = 1024 * Mem1MB
}
// now based on cfg, further clamp on calculated values
if cfg != nil && cfg.MaxTotalMemory != 0 {
availMemory = minUint64(cfg.MaxTotalMemory, availMemory)
}
// %20 of ram for sync only reserve
maxSyncMemory = uint64(availMemory * 2 / 10)
maxAsyncMemory = availMemory - maxSyncMemory
ramAsyncHWMark = maxAsyncMemory * 8 / 10
// For non-linux OS, we expect these (or their defaults) properly configured from command-line/env
logrus.WithFields(logrus.Fields{
"availMemory": availMemory,
"ramSync": maxSyncMemory,
"ramAsync": maxAsyncMemory,
"ramAsyncHWMark": ramAsyncHWMark,