VictoriaMetrics/lib/cgroup/mem.go
Aliaksandr Valialkin 077193d87c
lib/cgroup: reduce the default GOGC value from 50% to 30%
This reduces memory usage under production workloads by up to 10%,
while CPU spent on GC remains roughly the same.

The CPU spent on GC can be monitored with go_memstats_gc_cpu_fraction metric
2022-04-06 13:32:07 +03:00

88 lines
2.5 KiB
Go

package cgroup
import (
"os"
"runtime/debug"
"strconv"
)
// GetGOGC returns GOGC value for the currently running process.
//
// See https://golang.org/pkg/runtime/#hdr-Environment_Variables for more details about GOGC
func GetGOGC() int {
return gogc
}
func init() {
initGOGC()
}
func initGOGC() {
if v := os.Getenv("GOGC"); v != "" {
n, err := strconv.ParseFloat(v, 64)
if err != nil {
n = 100
}
gogc = int(n)
} else {
// Use lower GOGC if it isn't set yet.
// This should reduce memory usage for typical workloads for VictoriaMetrics components
// at the cost of increased CPU usage.
// It is recommended increasing GOGC if go_memstats_gc_cpu_fraction exceeds 0.05 for extended periods of time.
gogc = 30
debug.SetGCPercent(gogc)
}
}
var gogc int
// GetMemoryLimit returns cgroup memory limit
func GetMemoryLimit() int64 {
// Try determining the amount of memory inside docker container.
// See https://stackoverflow.com/questions/42187085/check-mem-limit-within-a-docker-container
//
// Read memory limit 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 limit inside lxc container.
// See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/84
n, err := getMemStat("memory.limit_in_bytes")
if err == nil {
return n
}
n, err = getMemStatV2("memory.max")
if err != nil {
return 0
}
return n
}
func getMemStatV2(statName string) (int64, error) {
// See https: //www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html#memory-interface-files
return getStatGeneric(statName, "/sys/fs/cgroup", "/proc/self/cgroup", "")
}
func getMemStat(statName string) (int64, error) {
return getStatGeneric(statName, "/sys/fs/cgroup/memory", "/proc/self/cgroup", "memory")
}
// GetHierarchicalMemoryLimit returns hierarchical memory limit
// https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt
func GetHierarchicalMemoryLimit() int64 {
// See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/699
n, err := getHierarchicalMemoryLimit("/sys/fs/cgroup/memory", "/proc/self/cgroup")
if err != nil {
return 0
}
return n
}
func getHierarchicalMemoryLimit(sysfsPrefix, cgroupPath string) (int64, error) {
data, err := getFileContents("memory.stat", sysfsPrefix, cgroupPath, "memory")
if err != nil {
return 0, err
}
memStat, err := grepFirstMatch(data, "hierarchical_memory_limit", 1, " ")
if err != nil {
return 0, err
}
return strconv.ParseInt(memStat, 10, 64)
}