Files
VictoriaMetrics/lib/memory/memory.go
Zhu Jiekun 3d3cc4bceb lib/memory: adds memory.allowedBytes warning message
This commit adds a warning message, if `-memory.allowedBytes` has value less than 1MB.

 It should help to debug possible issues, if there is a problem with app start-up due to low memory limit.

 For example, fastcache could panic at `-memory.allowedBytes=`

Fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/10935
2026-05-12 22:31:23 +02:00

76 lines
3.4 KiB
Go

package memory
import (
"flag"
"fmt"
"sync"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/flagutil"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
"github.com/VictoriaMetrics/metrics"
)
var (
allowedPercent = flag.Float64("memory.allowedPercent", 60, `Allowed percent of system memory VictoriaMetrics caches may occupy. See also -memory.allowedBytes. Too low a value may increase cache miss rate usually resulting in higher CPU and disk IO usage. Too high a value may evict too much data from the OS page cache which will result in higher disk IO usage`)
allowedBytes = flagutil.NewBytes("memory.allowedBytes", 0, `Allowed size of system memory VictoriaMetrics caches may occupy. This option overrides -memory.allowedPercent if set to a non-zero value. Too low a value may increase the cache miss rate usually resulting in higher CPU and disk IO usage. Too high a value may evict too much data from the OS page cache resulting in higher disk IO usage. The process may behave unexpectedly if this flag is set too small (e.g., 1 byte).`)
)
var _ = metrics.NewGauge("process_memory_limit_bytes", func() float64 {
return float64(memoryLimit)
})
var (
allowedMemory int
remainingMemory int
memoryLimit int
)
var once sync.Once
func initOnce() {
if !flag.Parsed() {
// Do not use logger.Panicf here, since logger may be uninitialized yet.
panic(fmt.Errorf("BUG: memory.Allowed must be called only after flag.Parse call"))
}
memoryLimit = sysTotalMemory()
if allowedBytes.N <= 0 {
if *allowedPercent < 1 || *allowedPercent > 100 {
logger.Fatalf("FATAL: -memory.allowedPercent must be in the range [1...100]; got %g", *allowedPercent)
}
percent := *allowedPercent / 100
allowedMemory = int(float64(memoryLimit) * percent)
remainingMemory = memoryLimit - allowedMemory
if remainingMemory <= 0 {
logger.Fatalf("BUG: remaining memory %d bytes cannot be less than or equal to zero, detected system memory limit %d bytes, -memory.allowedPercent=%g", remainingMemory, memoryLimit, *allowedPercent)
}
logger.Infof("limiting caches to %d bytes, leaving %d bytes to the OS according to -memory.allowedPercent=%g, system memory limit %d bytes", allowedMemory, remainingMemory, *allowedPercent, memoryLimit)
} else {
allowedMemory = allowedBytes.IntN()
if allowedMemory < 1*1024*1024 {
// It's fair to print a hint if the allowedBytes is set to too small, typically by misconfiguration.
logger.Warnf("allowed memory %d bytes set by -memory.allowedBytes is low. The process may behave unexpectedly.", allowedMemory)
}
remainingMemory = memoryLimit - allowedMemory
if remainingMemory <= 0 {
logger.Fatalf("FATAL: remaining memory %d bytes cannot be less than or equal to zero, detected system memory limit %d bytes, -memory.allowedBytes=%s", remainingMemory, memoryLimit, allowedBytes.String())
}
logger.Infof("limiting caches to %d bytes, leaving %d bytes to the OS according to -memory.allowedBytes=%s, system memory limit %d bytes", allowedMemory, remainingMemory, allowedBytes.String(), memoryLimit)
}
}
// Allowed returns the amount of system memory allowed to use by the app.
//
// The function must be called only after flag.Parse is called.
func Allowed() int {
once.Do(initOnce)
return allowedMemory
}
// Remaining returns the amount of memory remaining to the OS.
//
// This function must be called only after flag.Parse is called.
func Remaining() int {
once.Do(initOnce)
return remainingMemory
}