From 2c9e907912821712242c9daa8a7ae9c7c64b1c01 Mon Sep 17 00:00:00 2001
From: Giuseppe Scrivano <giuseppe@scrivano.org>
Date: Fri, 1 Nov 2019 20:51:24 +0100
Subject: cgroups: read correctly the CPU stats

the two values were incorrectly switched.

Signed-off-by: Giuseppe Scrivano <giuseppe@scrivano.org>
---
 pkg/cgroups/cpu.go | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/pkg/cgroups/cpu.go b/pkg/cgroups/cpu.go
index 03677f1ef..a43a76b22 100644
--- a/pkg/cgroups/cpu.go
+++ b/pkg/cgroups/cpu.go
@@ -81,14 +81,14 @@ func (c *cpuHandler) Stat(ctr *CgroupControl, m *Metrics) error {
 			return err
 		}
 		if val, found := values["usage_usec"]; found {
-			usage.Kernel, err = strconv.ParseUint(cleanString(val[0]), 10, 0)
+			usage.Total, err = strconv.ParseUint(cleanString(val[0]), 10, 0)
 			if err != nil {
 				return err
 			}
 			usage.Kernel *= 1000
 		}
 		if val, found := values["system_usec"]; found {
-			usage.Total, err = strconv.ParseUint(cleanString(val[0]), 10, 0)
+			usage.Kernel, err = strconv.ParseUint(cleanString(val[0]), 10, 0)
 			if err != nil {
 				return err
 			}
-- 
cgit v1.2.3-54-g00ecf


From a84ab35dc809f9ebedb290db234abdf43afe5a21 Mon Sep 17 00:00:00 2001
From: Giuseppe Scrivano <giuseppe@scrivano.org>
Date: Fri, 1 Nov 2019 20:52:08 +0100
Subject: stats: fix calculation for the CPU time

Closes: https://github.com/containers/libpod/issues/4409

Signed-off-by: Giuseppe Scrivano <giuseppe@scrivano.org>
---
 libpod/stats.go | 24 +++++++++++-------------
 1 file changed, 11 insertions(+), 13 deletions(-)

diff --git a/libpod/stats.go b/libpod/stats.go
index 5513abce5..3b5e0958c 100644
--- a/libpod/stats.go
+++ b/libpod/stats.go
@@ -3,7 +3,6 @@
 package libpod
 
 import (
-	"runtime"
 	"strings"
 	"syscall"
 	"time"
@@ -56,8 +55,8 @@ func (c *Container) GetContainerStats(previousStats *ContainerStats) (*Container
 	}
 
 	previousCPU := previousStats.CPUNano
-	previousSystem := previousStats.SystemNano
-	stats.CPU = calculateCPUPercent(cgroupStats, previousCPU, previousSystem)
+	now := uint64(time.Now().UnixNano())
+	stats.CPU = calculateCPUPercent(cgroupStats, previousCPU, now, previousStats.SystemNano)
 	stats.MemUsage = cgroupStats.Memory.Usage.Usage
 	stats.MemLimit = getMemLimit(cgroupStats.Memory.Usage.Limit)
 	stats.MemPerc = (float64(stats.MemUsage) / float64(stats.MemLimit)) * 100
@@ -67,7 +66,7 @@ func (c *Container) GetContainerStats(previousStats *ContainerStats) (*Container
 	}
 	stats.BlockInput, stats.BlockOutput = calculateBlockIO(cgroupStats)
 	stats.CPUNano = cgroupStats.CPU.Usage.Total
-	stats.SystemNano = cgroupStats.CPU.Usage.Kernel
+	stats.SystemNano = now
 	// Handle case where the container is not in a network namespace
 	if netStats != nil {
 		stats.NetInput = netStats.TxBytes
@@ -98,20 +97,19 @@ func getMemLimit(cgroupLimit uint64) uint64 {
 	return cgroupLimit
 }
 
-func calculateCPUPercent(stats *cgroups.Metrics, previousCPU, previousSystem uint64) float64 {
+// calculateCPUPercent calculates the cpu usage using the latest measurement in stats.
+// previousCPU is the last value of stats.CPU.Usage.Total measured at the time previousSystem.
+//  (now - previousSystem) is the time delta in nanoseconds, between the measurement in previousCPU
+// and the updated value in stats.
+func calculateCPUPercent(stats *cgroups.Metrics, previousCPU, now, previousSystem uint64) float64 {
 	var (
 		cpuPercent  = 0.0
 		cpuDelta    = float64(stats.CPU.Usage.Total - previousCPU)
-		systemDelta = float64(uint64(time.Now().UnixNano()) - previousSystem)
+		systemDelta = float64(now - previousSystem)
 	)
 	if systemDelta > 0.0 && cpuDelta > 0.0 {
-		// gets a ratio of container cpu usage total, multiplies it by the number of cores (4 cores running
-		// at 100% utilization should be 400% utilization), and multiplies that by 100 to get a percentage
-		nCPUS := len(stats.CPU.Usage.PerCPU)
-		if nCPUS == 0 {
-			nCPUS = runtime.NumCPU()
-		}
-		cpuPercent = (cpuDelta / systemDelta) * float64(nCPUS) * 100
+		// gets a ratio of container cpu usage total, and multiplies that by 100 to get a percentage
+		cpuPercent = (cpuDelta / systemDelta) * 100
 	}
 	return cpuPercent
 }
-- 
cgit v1.2.3-54-g00ecf