From 82600b7021232ecd3c7c77cf18d0f86f5d17f48b Mon Sep 17 00:00:00 2001 From: Sergey Tryuber Date: Thu, 27 Apr 2017 22:17:47 +0400 Subject: [PATCH] Adjusted docker stats memory output Signed-off-by: Sergey Tryuber Signed-off-by: Akihiro Suda --- cli/command/container/stats_helpers.go | 28 +++++++++----- cli/command/container/stats_helpers_test.go | 42 +++++++++++++++++++++ 2 files changed, 61 insertions(+), 9 deletions(-) create mode 100644 cli/command/container/stats_helpers_test.go diff --git a/cli/command/container/stats_helpers.go b/cli/command/container/stats_helpers.go index 586f4908b1..c6849c805a 100644 --- a/cli/command/container/stats_helpers.go +++ b/cli/command/container/stats_helpers.go @@ -84,7 +84,7 @@ func collect(ctx context.Context, s *formatter.ContainerStats, cli client.APICli v *types.StatsJSON memPercent, cpuPercent float64 blkRead, blkWrite uint64 // Only used on Linux - mem, memLimit, memPerc float64 + mem, memLimit float64 pidsStatsCurrent uint64 ) @@ -101,18 +101,13 @@ func collect(ctx context.Context, s *formatter.ContainerStats, cli client.APICli daemonOSType = response.OSType if daemonOSType != "windows" { - // MemoryStats.Limit will never be 0 unless the container is not running and we haven't - // got any data from cgroup - if v.MemoryStats.Limit != 0 { - memPercent = float64(v.MemoryStats.Usage) / float64(v.MemoryStats.Limit) * 100.0 - } previousCPU = v.PreCPUStats.CPUUsage.TotalUsage previousSystem = v.PreCPUStats.SystemUsage cpuPercent = calculateCPUPercentUnix(previousCPU, previousSystem, v) blkRead, blkWrite = calculateBlockIO(v.BlkioStats) - mem = float64(v.MemoryStats.Usage) + mem = calculateMemUsageUnixNoCache(v.MemoryStats) memLimit = float64(v.MemoryStats.Limit) - memPerc = memPercent + memPercent = calculateMemPercentUnixNoCache(memLimit, mem) pidsStatsCurrent = v.PidsStats.Current } else { cpuPercent = calculateCPUPercentWindows(v) @@ -126,7 +121,7 @@ func collect(ctx context.Context, s *formatter.ContainerStats, cli client.APICli ID: v.ID, CPUPercentage: cpuPercent, Memory: mem, - MemoryPercentage: memPerc, + MemoryPercentage: memPercent, MemoryLimit: memLimit, NetworkRx: netRx, NetworkTx: netTx, @@ -227,3 +222,18 @@ func calculateNetwork(network map[string]types.NetworkStats) (float64, float64) } return rx, tx } + +// calculateMemUsageUnixNoCache calculate memory usage of the container. +// Page cache is intentionally excluded to avoid misinterpretation of the output. +func calculateMemUsageUnixNoCache(mem types.MemoryStats) float64 { + return float64(mem.Usage - mem.Stats["cache"]) +} + +func calculateMemPercentUnixNoCache(limit float64, usedNoCache float64) float64 { + // MemoryStats.Limit will never be 0 unless the container is not running and we haven't + // got any data from cgroup + if limit != 0 { + return usedNoCache / limit * 100.0 + } + return 0 +} diff --git a/cli/command/container/stats_helpers_test.go b/cli/command/container/stats_helpers_test.go new file mode 100644 index 0000000000..589ee8f66f --- /dev/null +++ b/cli/command/container/stats_helpers_test.go @@ -0,0 +1,42 @@ +package container + +import ( + "github.com/docker/docker/api/types" + "testing" +) + +func TestCalculateMemUsageUnixNoCache(t *testing.T) { + // Given + stats := types.MemoryStats{Usage: 500, Stats: map[string]uint64{"cache": 400}} + + // When + result := calculateMemUsageUnixNoCache(stats) + + // Then + if result != 100 { + t.Errorf("mem = %d, want 100", result) + } +} + +func TestCalculateMemPercentUnixNoCache(t *testing.T) { + // Given + someLimit := float64(100.0) + noLimit := float64(0.0) + used := float64(70.0) + + // When and Then + t.Run("Limit is set", func(t *testing.T) { + result := calculateMemPercentUnixNoCache(someLimit, used) + expected := float64(70.0) + if result != expected { + t.Errorf("percent = %f, want %f", result, expected) + } + }) + t.Run("No limit, no cgroup data", func(t *testing.T) { + result := calculateMemPercentUnixNoCache(noLimit, used) + expected := float64(0.0) + if result != expected { + t.Errorf("percent = %f, want %f", result, expected) + } + }) +}