From 5d29598a6d5db2405befb15c83c7f95cd42ae5fe Mon Sep 17 00:00:00 2001 From: Lantao Liu Date: Fri, 11 May 2018 14:57:13 -0700 Subject: [PATCH] Fix workingset memory calculation. Signed-off-by: Lantao Liu --- pkg/server/container_stats_list.go | 20 ++++++++- pkg/server/container_stats_list_test.go | 55 +++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 pkg/server/container_stats_list_test.go diff --git a/pkg/server/container_stats_list.go b/pkg/server/container_stats_list.go index 3b4d8c93d..f0605ef77 100644 --- a/pkg/server/container_stats_list.go +++ b/pkg/server/container_stats_list.go @@ -109,8 +109,10 @@ func (c *criService) getContainerMetrics( } if metrics.Memory != nil && metrics.Memory.Usage != nil { cs.Memory = &runtime.MemoryUsage{ - Timestamp: stats.Timestamp.UnixNano(), - WorkingSetBytes: &runtime.UInt64Value{Value: metrics.Memory.Usage.Usage}, + Timestamp: stats.Timestamp.UnixNano(), + WorkingSetBytes: &runtime.UInt64Value{ + Value: getWorkingSet(metrics.Memory), + }, } } } @@ -167,3 +169,17 @@ func matchLabelSelector(selector, labels map[string]string) bool { } return true } + +// getWorkingSet calculates workingset memory from cgroup memory stats. +// The caller should make sure memory is not nil. +// workingset = usage - total_inactive_file +func getWorkingSet(memory *cgroups.MemoryStat) uint64 { + if memory.Usage == nil { + return 0 + } + var workingSet uint64 + if memory.TotalInactiveFile < memory.Usage.Usage { + workingSet = memory.Usage.Usage - memory.TotalInactiveFile + } + return workingSet +} diff --git a/pkg/server/container_stats_list_test.go b/pkg/server/container_stats_list_test.go new file mode 100644 index 000000000..9774ee4b8 --- /dev/null +++ b/pkg/server/container_stats_list_test.go @@ -0,0 +1,55 @@ +/* +Copyright 2018 The containerd Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package server + +import ( + "testing" + + "github.com/containerd/cgroups" + "github.com/stretchr/testify/assert" +) + +func TestGetWorkingSet(t *testing.T) { + for desc, test := range map[string]struct { + memory *cgroups.MemoryStat + expected uint64 + }{ + "nil memory usage": { + memory: &cgroups.MemoryStat{}, + expected: 0, + }, + "memory usage higher than inactive_total_file": { + memory: &cgroups.MemoryStat{ + TotalInactiveFile: 1000, + Usage: &cgroups.MemoryEntry{Usage: 2000}, + }, + expected: 1000, + }, + "memory usage lower than inactive_total_file": { + memory: &cgroups.MemoryStat{ + TotalInactiveFile: 2000, + Usage: &cgroups.MemoryEntry{Usage: 1000}, + }, + expected: 0, + }, + } { + t.Run(desc, func(t *testing.T) { + got := getWorkingSet(test.memory) + assert.Equal(t, test.expected, got) + }) + } +}