From 82600b7021232ecd3c7c77cf18d0f86f5d17f48b Mon Sep 17 00:00:00 2001 From: Sergey Tryuber Date: Thu, 27 Apr 2017 22:17:47 +0400 Subject: [PATCH 1/2] 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 586f4908b1b8..c6849c805aeb 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 000000000000..589ee8f66f18 --- /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) + } + }) +} From 3c78bc775c21c238eb534e3d2631695b4c09a215 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Sat, 13 May 2017 23:23:15 +0000 Subject: [PATCH 2/2] Fix float64 comparison in stats_helpers_test.go Signed-off-by: Akihiro Suda --- cli/command/container/stats_helpers_test.go | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/cli/command/container/stats_helpers_test.go b/cli/command/container/stats_helpers_test.go index 589ee8f66f18..0425a3ba13d3 100644 --- a/cli/command/container/stats_helpers_test.go +++ b/cli/command/container/stats_helpers_test.go @@ -1,8 +1,10 @@ package container import ( - "github.com/docker/docker/api/types" "testing" + + "github.com/docker/docker/api/types" + "github.com/stretchr/testify/assert" ) func TestCalculateMemUsageUnixNoCache(t *testing.T) { @@ -13,9 +15,7 @@ func TestCalculateMemUsageUnixNoCache(t *testing.T) { result := calculateMemUsageUnixNoCache(stats) // Then - if result != 100 { - t.Errorf("mem = %d, want 100", result) - } + assert.InDelta(t, 100.0, result, 1e-6) } func TestCalculateMemPercentUnixNoCache(t *testing.T) { @@ -27,16 +27,10 @@ func TestCalculateMemPercentUnixNoCache(t *testing.T) { // 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) - } + assert.InDelta(t, 70.0, result, 1e-6) }) 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) - } + assert.InDelta(t, 0.0, result, 1e-6) }) }