stats: get the memory limit from the spec

OCI runtimes may set the memory limits in different ways, e.g., crun
creates a sub-cgroup where the limits are applied, while runc applies
them directly on the created cgroup.  Since there is standardization
on the cgroup path to use, just use the limit specified in the spec
file.

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
Giuseppe Scrivano
2021-11-24 13:41:02 +01:00
parent 4b014a3aec
commit b25b330306

View File

@ -3,6 +3,7 @@
package libpod package libpod
import ( import (
"math"
"strings" "strings"
"syscall" "syscall"
"time" "time"
@ -68,7 +69,7 @@ func (c *Container) GetContainerStats(previousStats *define.ContainerStats) (*de
stats.AvgCPU = calculateAvgCPU(stats.CPU, previousStats.AvgCPU, previousStats.DataPoints) stats.AvgCPU = calculateAvgCPU(stats.CPU, previousStats.AvgCPU, previousStats.DataPoints)
stats.DataPoints = previousStats.DataPoints + 1 stats.DataPoints = previousStats.DataPoints + 1
stats.MemUsage = cgroupStats.Memory.Usage.Usage stats.MemUsage = cgroupStats.Memory.Usage.Usage
stats.MemLimit = getMemLimit(cgroupStats.Memory.Usage.Limit) stats.MemLimit = c.getMemLimit()
stats.MemPerc = (float64(stats.MemUsage) / float64(stats.MemLimit)) * 100 stats.MemPerc = (float64(stats.MemUsage) / float64(stats.MemLimit)) * 100
stats.PIDs = 0 stats.PIDs = 0
if conState == define.ContainerStateRunning || conState == define.ContainerStatePaused { if conState == define.ContainerStateRunning || conState == define.ContainerStatePaused {
@ -91,22 +92,29 @@ func (c *Container) GetContainerStats(previousStats *define.ContainerStats) (*de
return stats, nil return stats, nil
} }
// getMemory limit returns the memory limit for a given cgroup // getMemory limit returns the memory limit for a container
// If the configured memory limit is larger than the total memory on the sys, the func (c *Container) getMemLimit() uint64 {
// physical system memory size is returned memLimit := uint64(math.MaxUint64)
func getMemLimit(cgroupLimit uint64) uint64 {
if c.config.Spec.Linux != nil && c.config.Spec.Linux.Resources != nil &&
c.config.Spec.Linux.Resources.Memory != nil && c.config.Spec.Linux.Resources.Memory.Limit != nil {
memLimit = uint64(*c.config.Spec.Linux.Resources.Memory.Limit)
}
si := &syscall.Sysinfo_t{} si := &syscall.Sysinfo_t{}
err := syscall.Sysinfo(si) err := syscall.Sysinfo(si)
if err != nil { if err != nil {
return cgroupLimit return memLimit
} }
//nolint:unconvert //nolint:unconvert
physicalLimit := uint64(si.Totalram) physicalLimit := uint64(si.Totalram)
if cgroupLimit > physicalLimit {
if memLimit <= 0 || memLimit > physicalLimit {
return physicalLimit return physicalLimit
} }
return cgroupLimit
return memLimit
} }
// calculateCPUPercent calculates the cpu usage using the latest measurement in stats. // calculateCPUPercent calculates the cpu usage using the latest measurement in stats.