diff --git a/lib/cgroup/mem.go b/lib/cgroup/mem.go index 716c21b0d..0141371a7 100644 --- a/lib/cgroup/mem.go +++ b/lib/cgroup/mem.go @@ -14,3 +14,18 @@ func GetMemoryLimit() int64 { } return n } + +// GetHierarchicalMemoryLimit returns hierarchical memory limit +func GetHierarchicalMemoryLimit() int64 { + // See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/699 + n, err := readInt64FromCommand("cat /sys/fs/cgroup/memory/memory.stat | grep hierarchical_memory_limit | cut -d' ' -f 2") + if err == nil { + return n + } + n, err = readInt64FromCommand( + "cat /sys/fs/cgroup/memory$(cat /proc/self/cgroup | grep memory | cut -d: -f3)/memory.stat | grep hierarchical_memory_limit | cut -d' ' -f 2") + if err != nil { + return 0 + } + return n +} diff --git a/lib/cgroup/util.go b/lib/cgroup/util.go index 337b8fa3b..eb1ca8b04 100644 --- a/lib/cgroup/util.go +++ b/lib/cgroup/util.go @@ -9,15 +9,18 @@ import ( func readInt64(path, altCommand string) (int64, error) { data, err := ioutil.ReadFile(path) + if err == nil { + data = bytes.TrimSpace(data) + return strconv.ParseInt(string(data), 10, 64) + } + return readInt64FromCommand(altCommand) +} + +func readInt64FromCommand(command string) (int64, error) { + cmd := exec.Command("/bin/sh", "-c", command) + data, err := cmd.Output() if err != nil { - // Read data according to https://unix.stackexchange.com/questions/242718/how-to-find-out-how-much-memory-lxc-container-is-allowed-to-consume - // This should properly determine the data location inside lxc container. - // See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/84 - cmd := exec.Command("/bin/sh", "-c", altCommand) - data, err = cmd.Output() - if err != nil { - return 0, err - } + return 0, err } data = bytes.TrimSpace(data) return strconv.ParseInt(string(data), 10, 64) diff --git a/lib/memory/memory_linux.go b/lib/memory/memory_linux.go index 5ad333748..05b2c190a 100644 --- a/lib/memory/memory_linux.go +++ b/lib/memory/memory_linux.go @@ -20,7 +20,12 @@ func sysTotalMemory() int { } mem := cgroup.GetMemoryLimit() if mem <= 0 || int64(int(mem)) != mem || int(mem) > totalMem { - return totalMem + // Try reading hierachical memory limit. + // See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/699 + mem = cgroup.GetHierarchicalMemoryLimit() + if mem <= 0 || int64(int(mem)) != mem || int(mem) > totalMem { + return totalMem + } } return int(mem) }