From 54a5077ca584bf860031d9d1e3a8cffdeda9d6c1 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Mon, 6 Mar 2017 17:29:09 +0000 Subject: [PATCH] Correct CPU usage calculation in presence of offline CPUs and newer Linux In https://github.com/torvalds/linux/commit/5ca3726 (released in v4.7-rc1) the content of the `cpuacct.usage_percpu` file in sysfs was changed to include both online and offline cpus. This broke the arithmetic in the stats helpers used by `docker stats`, since it was using the length of the PerCPUUsage array as a proxy for the number of online CPUs. Add current number of online CPUs to types.StatsJSON and use it in the calculation. Keep a fallback to `len(v.CPUStats.CPUUsage.PercpuUsage)` so this code continues to work when talking to an older daemon. An old client talking to a new daemon will ignore the new field and behave as before. Fixes #28941. Signed-off-by: Ian Campbell --- command/container/stats_helpers.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/command/container/stats_helpers.go b/command/container/stats_helpers.go index 5fad740435..3dc939a137 100644 --- a/command/container/stats_helpers.go +++ b/command/container/stats_helpers.go @@ -178,10 +178,14 @@ func calculateCPUPercentUnix(previousCPU, previousSystem uint64, v *types.StatsJ cpuDelta = float64(v.CPUStats.CPUUsage.TotalUsage) - float64(previousCPU) // calculate the change for the entire system between readings systemDelta = float64(v.CPUStats.SystemUsage) - float64(previousSystem) + onlineCPUs = float64(v.CPUStats.OnlineCPUs) ) + if onlineCPUs == 0.0 { + onlineCPUs = float64(len(v.CPUStats.CPUUsage.PercpuUsage)) + } if systemDelta > 0.0 && cpuDelta > 0.0 { - cpuPercent = (cpuDelta / systemDelta) * float64(len(v.CPUStats.CPUUsage.PercpuUsage)) * 100.0 + cpuPercent = (cpuDelta / systemDelta) * onlineCPUs * 100.0 } return cpuPercent }