diff --git a/pkg/agent/sysadvisor/plugin/qosaware/resource/memory/advisor.go b/pkg/agent/sysadvisor/plugin/qosaware/resource/memory/advisor.go index 4d6fc7454..6ba0d2e70 100644 --- a/pkg/agent/sysadvisor/plugin/qosaware/resource/memory/advisor.go +++ b/pkg/agent/sysadvisor/plugin/qosaware/resource/memory/advisor.go @@ -41,6 +41,7 @@ import ( func init() { headroompolicy.RegisterInitializer(types.MemoryHeadroomPolicyCanonical, headroompolicy.NewPolicyCanonical) + headroompolicy.RegisterInitializer(types.MemoryHeadroomPolicyNUMAAware, headroompolicy.NewPolicyNUMAAware) memadvisorplugin.RegisterInitializer(memadvisorplugin.CacheReaper, memadvisorplugin.NewCacheReaper) memadvisorplugin.RegisterInitializer(memadvisorplugin.MemoryGuard, memadvisorplugin.NewMemoryGuard) @@ -98,7 +99,10 @@ func NewMemoryResourceAdvisor(conf *config.Configuration, extraConf interface{}, klog.Errorf("failed to find registered initializer %v", headroomPolicyName) continue } - ra.headroomPolices = append(ra.headroomPolices, initFunc(conf, extraConf, metaCache, metaServer, emitter)) + policy := initFunc(conf, extraConf, metaCache, metaServer, emitter) + general.InfoS("add new memory headroom policy", "policyName", policy.Name()) + + ra.headroomPolices = append(ra.headroomPolices, policy) } memoryAdvisorPluginInitializers := memadvisorplugin.GetRegisteredInitializers() @@ -108,6 +112,7 @@ func NewMemoryResourceAdvisor(conf *config.Configuration, extraConf interface{}, klog.Errorf("failed to find registered initializer %v", memadvisorPluginName) continue } + general.InfoS("add new memory advisor policy", "policyName", memadvisorPluginName) ra.plugins = append(ra.plugins, initFunc(conf, extraConf, metaCache, metaServer, emitter)) } @@ -135,7 +140,7 @@ func (ra *memoryResourceAdvisor) GetHeadroom() (resource.Quantity, error) { for _, headroomPolicy := range ra.headroomPolices { headroom, err := headroomPolicy.GetHeadroom() if err != nil { - klog.Warningf("[qosaware-memory] get headroom with error: %v", err) + klog.ErrorS(err, "get headroom failed", "headroomPolicy", headroomPolicy.Name()) continue } return headroom, nil @@ -182,7 +187,7 @@ func (ra *memoryResourceAdvisor) update() { }) if err := headroomPolicy.Update(); err != nil { - klog.Errorf("[qosaware-memory] update headroom policy failed: %v", err) + general.ErrorS(err, "[qosaware-memory] update headroom policy failed", "headroomPolicy", headroomPolicy.Name()) } } diff --git a/pkg/agent/sysadvisor/plugin/qosaware/resource/memory/headroompolicy/policy.go b/pkg/agent/sysadvisor/plugin/qosaware/resource/memory/headroompolicy/policy.go index c79c428e4..1ac8c8bf7 100644 --- a/pkg/agent/sysadvisor/plugin/qosaware/resource/memory/headroompolicy/policy.go +++ b/pkg/agent/sysadvisor/plugin/qosaware/resource/memory/headroompolicy/policy.go @@ -30,6 +30,7 @@ import ( // HeadroomPolicy generates resource headroom estimation based on configured algorithm type HeadroomPolicy interface { + Name() types.MemoryHeadroomPolicyName // SetPodSet overwrites policy's pod/container record SetPodSet(types.PodSet) diff --git a/pkg/agent/sysadvisor/plugin/qosaware/resource/memory/headroompolicy/policy_canonical.go b/pkg/agent/sysadvisor/plugin/qosaware/resource/memory/headroompolicy/policy_canonical.go index 9a18e3239..9e0473824 100644 --- a/pkg/agent/sysadvisor/plugin/qosaware/resource/memory/headroompolicy/policy_canonical.go +++ b/pkg/agent/sysadvisor/plugin/qosaware/resource/memory/headroompolicy/policy_canonical.go @@ -56,6 +56,10 @@ func NewPolicyCanonical(conf *config.Configuration, _ interface{}, metaReader me return &p } +func (p *PolicyCanonical) Name() types.MemoryHeadroomPolicyName { + return types.MemoryHeadroomPolicyCanonical +} + // estimateNonReclaimedQoSMemoryRequirement estimates the memory requirement of all containers that are not reclaimed func (p *PolicyCanonical) estimateNonReclaimedQoSMemoryRequirement() (float64, error) { var ( diff --git a/pkg/agent/sysadvisor/plugin/qosaware/resource/memory/headroompolicy/policy_numa_aware.go b/pkg/agent/sysadvisor/plugin/qosaware/resource/memory/headroompolicy/policy_numa_aware.go new file mode 100644 index 000000000..1ee711eff --- /dev/null +++ b/pkg/agent/sysadvisor/plugin/qosaware/resource/memory/headroompolicy/policy_numa_aware.go @@ -0,0 +1,155 @@ +/* +Copyright 2022 The Katalyst 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 headroompolicy + +import ( + "context" + "fmt" + "strconv" + + "k8s.io/apimachinery/pkg/api/resource" + "k8s.io/apimachinery/pkg/util/errors" + + apiconsts "github.com/kubewharf/katalyst-api/pkg/consts" + "github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/metacache" + "github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/plugin/qosaware/resource/helper" + "github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/types" + "github.com/kubewharf/katalyst-core/pkg/config" + "github.com/kubewharf/katalyst-core/pkg/consts" + "github.com/kubewharf/katalyst-core/pkg/metaserver" + "github.com/kubewharf/katalyst-core/pkg/metrics" + "github.com/kubewharf/katalyst-core/pkg/util/general" + "github.com/kubewharf/katalyst-core/pkg/util/machine" + "github.com/kubewharf/katalyst-core/pkg/util/metric" +) + +type PolicyNUMAAware struct { + *PolicyBase + + // memoryHeadroom is valid to be used iff updateStatus successes + memoryHeadroom float64 + updateStatus types.PolicyUpdateStatus + + conf *config.Configuration +} + +func NewPolicyNUMAAware(conf *config.Configuration, _ interface{}, metaReader metacache.MetaReader, + metaServer *metaserver.MetaServer, _ metrics.MetricEmitter) HeadroomPolicy { + p := PolicyNUMAAware{ + PolicyBase: NewPolicyBase(metaReader, metaServer), + updateStatus: types.PolicyUpdateFailed, + conf: conf, + } + + return &p +} + +func (p *PolicyNUMAAware) Name() types.MemoryHeadroomPolicyName { + return types.MemoryHeadroomPolicyNUMAAware +} + +func (p *PolicyNUMAAware) reclaimedContainersFilter(ci *types.ContainerInfo) bool { + return ci != nil && ci.QoSLevel == apiconsts.PodAnnotationQoSLevelReclaimedCores +} + +func (p *PolicyNUMAAware) Update() (err error) { + defer func() { + if err != nil { + p.updateStatus = types.PolicyUpdateFailed + } else { + p.updateStatus = types.PolicyUpdateSucceeded + } + }() + + var ( + errList []error + reclaimableMemory float64 + data metric.MetricData + ) + + availNUMAs := p.metaServer.CPUDetails.NUMANodes() + + reclaimedCoresContainers := make([]*types.ContainerInfo, 0) + p.metaReader.RangeContainer(func(podUID string, containerName string, containerInfo *types.ContainerInfo) bool { + if p.reclaimedContainersFilter(containerInfo) { + reclaimedCoresContainers = append(reclaimedCoresContainers, containerInfo) + return true + } + + nodeReclaim := p.conf.GetDynamicConfiguration().EnableReclaim + reclaimEnable, err := helper.PodEnableReclaim(context.Background(), p.metaServer, podUID, nodeReclaim) + if err != nil { + errList = append(errList, err) + return true + } + + if containerInfo.IsNumaExclusive() && !reclaimEnable { + memset := machine.GetCPUAssignmentNUMAs(containerInfo.TopologyAwareAssignments) + if memset.IsEmpty() { + errList = append(errList, fmt.Errorf("container(%v/%v) TopologyAwareAssignments is empty", containerInfo.PodName, containerName)) + return true + } + availNUMAs = availNUMAs.Difference(memset) + } + return true + }) + + err = errors.NewAggregate(errList) + if err != nil { + return err + } + + for _, numaID := range availNUMAs.ToSliceInt() { + data, err = p.metaServer.GetNumaMetric(numaID, consts.MetricMemFreeNuma) + if err != nil { + return err + } + numaFree := data.Value + + reclaimedCoresUsed := 0. + for _, container := range reclaimedCoresContainers { + data, err = p.metaServer.GetContainerNumaMetric(container.PodUID, container.ContainerName, strconv.Itoa(numaID), consts.MetricsMemTotalPerNumaContainer) + if err != nil { + general.ErrorS(err, "failed to get metric", "name", consts.MetricsMemTotalPerNumaContainer, + "podName", container.PodName, "ContainerName", container.ContainerName, "numaID", numaID) + return err + } + reclaimedCoresUsed += data.Value + general.InfoS("container memory", "podName", container.PodName, "containerName", container.ContainerName, "numaID", numaID, "memory used", general.FormatMemoryQuantity(data.Value)) + } + + reclaimableMemory += numaFree + reclaimedCoresUsed + + general.InfoS("memory reclaimable", "numaID", numaID, "numaFree", general.FormatMemoryQuantity(numaFree), "reclaimable", general.FormatMemoryQuantity(numaFree+reclaimedCoresUsed)) + } + + general.InfoS("total memory reclaimable", + "reclaimableMemory", general.FormatMemoryQuantity(reclaimableMemory), + "ReservedForAllocate", general.FormatMemoryQuantity(p.essentials.ReservedForAllocate), + "ResourceUpperBound", general.FormatMemoryQuantity(p.essentials.ResourceUpperBound)) + p.memoryHeadroom = general.Clamp(reclaimableMemory-p.essentials.ReservedForAllocate, 0, p.essentials.ResourceUpperBound) + + return nil +} + +func (p *PolicyNUMAAware) GetHeadroom() (resource.Quantity, error) { + if p.updateStatus != types.PolicyUpdateSucceeded { + return resource.Quantity{}, fmt.Errorf("last update failed") + } + + return *resource.NewQuantity(int64(p.memoryHeadroom), resource.BinarySI), nil +} diff --git a/pkg/agent/sysadvisor/plugin/qosaware/resource/memory/headroompolicy/policy_numa_aware_test.go b/pkg/agent/sysadvisor/plugin/qosaware/resource/memory/headroompolicy/policy_numa_aware_test.go new file mode 100644 index 000000000..9713a1543 --- /dev/null +++ b/pkg/agent/sysadvisor/plugin/qosaware/resource/memory/headroompolicy/policy_numa_aware_test.go @@ -0,0 +1,198 @@ +/* +Copyright 2022 The Katalyst 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 headroompolicy + +import ( + "io/ioutil" + "os" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + + "github.com/kubewharf/katalyst-api/pkg/consts" + "github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/metacache" + "github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/types" + pkgconsts "github.com/kubewharf/katalyst-core/pkg/consts" + "github.com/kubewharf/katalyst-core/pkg/metaserver/agent/metric" + "github.com/kubewharf/katalyst-core/pkg/metrics" + metricspool "github.com/kubewharf/katalyst-core/pkg/metrics/metrics-pool" + "github.com/kubewharf/katalyst-core/pkg/util/machine" + utilmetric "github.com/kubewharf/katalyst-core/pkg/util/metric" +) + +func TestPolicyNUMAAware(t *testing.T) { + t.Parallel() + + now := time.Now() + + type fields struct { + podList []*v1.Pod + containers []*types.ContainerInfo + essentials types.ResourceEssentials + setFakeMetric func(store *metric.FakeMetricsFetcher) + } + tests := []struct { + name string + fields fields + want resource.Quantity + wantErr bool + }{ + { + name: "numa metrics missing", + fields: fields{ + podList: []*v1.Pod{}, + containers: []*types.ContainerInfo{}, + essentials: types.ResourceEssentials{ + EnableReclaim: true, + ResourceUpperBound: 100 << 30, + ReservedForAllocate: 4 << 30, + }, + setFakeMetric: func(store *metric.FakeMetricsFetcher) { + store.SetNumaMetric(0, pkgconsts.MetricMemFreeNuma, utilmetric.MetricData{Value: 100 << 30, Time: &now}) + }, + }, + wantErr: true, + }, + { + name: "normal: no containers", + fields: fields{ + podList: []*v1.Pod{}, + containers: []*types.ContainerInfo{}, + essentials: types.ResourceEssentials{ + EnableReclaim: true, + ResourceUpperBound: 400 << 30, + ReservedForAllocate: 4 << 30, + }, + setFakeMetric: func(store *metric.FakeMetricsFetcher) { + store.SetNumaMetric(0, pkgconsts.MetricMemFreeNuma, utilmetric.MetricData{Value: 100 << 30, Time: &now}) + store.SetNumaMetric(1, pkgconsts.MetricMemFreeNuma, utilmetric.MetricData{Value: 100 << 30, Time: &now}) + }, + }, + wantErr: false, + want: resource.MustParse("196Gi"), + }, + { + name: "normal: reclaimed_cores containers only", + fields: fields{ + podList: []*v1.Pod{}, + containers: []*types.ContainerInfo{ + makeContainerInfo("pod1", "default", + "pod1", "container1", + consts.PodAnnotationQoSLevelReclaimedCores, nil, + nil, 1), + }, + essentials: types.ResourceEssentials{ + EnableReclaim: true, + ResourceUpperBound: 400 << 30, + ReservedForAllocate: 4 << 30, + }, + setFakeMetric: func(store *metric.FakeMetricsFetcher) { + store.SetNumaMetric(0, pkgconsts.MetricMemFreeNuma, utilmetric.MetricData{Value: 100 << 30, Time: &now}) + store.SetNumaMetric(1, pkgconsts.MetricMemFreeNuma, utilmetric.MetricData{Value: 100 << 30, Time: &now}) + + store.SetContainerNumaMetric("pod1", "container1", "0", pkgconsts.MetricsMemTotalPerNumaContainer, utilmetric.MetricData{Value: 20 << 30, Time: &now}) + store.SetContainerNumaMetric("pod1", "container1", "1", pkgconsts.MetricsMemTotalPerNumaContainer, utilmetric.MetricData{Value: 20 << 30, Time: &now}) + }, + }, + wantErr: false, + want: resource.MustParse("236Gi"), + }, + { + name: "normal: reclaimed_cores containers with numa-exclusive containers", + fields: fields{ + podList: []*v1.Pod{}, + containers: []*types.ContainerInfo{ + makeContainerInfo("pod1", "default", + "pod1", "container1", + consts.PodAnnotationQoSLevelReclaimedCores, nil, + nil, 1), + makeContainerInfo("pod2", "default", + "pod2", "container2", + consts.PodAnnotationQoSLevelDedicatedCores, map[string]string{ + consts.PodAnnotationMemoryEnhancementNumaBinding: consts.PodAnnotationMemoryEnhancementNumaBindingEnable, + consts.PodAnnotationMemoryEnhancementNumaExclusive: consts.PodAnnotationMemoryEnhancementNumaExclusiveEnable, + }, + types.TopologyAwareAssignment{ + 0: machine.NewCPUSet(0), + }, 1)}, + essentials: types.ResourceEssentials{ + EnableReclaim: true, + ResourceUpperBound: 400 << 30, + ReservedForAllocate: 4 << 30, + }, + setFakeMetric: func(store *metric.FakeMetricsFetcher) { + store.SetNumaMetric(0, pkgconsts.MetricMemFreeNuma, utilmetric.MetricData{Value: 100 << 30, Time: &now}) + store.SetNumaMetric(1, pkgconsts.MetricMemFreeNuma, utilmetric.MetricData{Value: 100 << 30, Time: &now}) + + store.SetContainerNumaMetric("pod1", "container1", "0", pkgconsts.MetricsMemTotalPerNumaContainer, utilmetric.MetricData{Value: 20 << 30, Time: &now}) + store.SetContainerNumaMetric("pod1", "container1", "1", pkgconsts.MetricsMemTotalPerNumaContainer, utilmetric.MetricData{Value: 20 << 30, Time: &now}) + }, + }, + wantErr: false, + want: resource.MustParse("116Gi"), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ckDir, err := ioutil.TempDir("", "checkpoint-TestPolicyNUMAAware") + require.NoError(t, err) + defer os.RemoveAll(ckDir) + + sfDir, err := ioutil.TempDir("", "statefile") + require.NoError(t, err) + defer os.RemoveAll(sfDir) + + conf := generateTestConfiguration(t, ckDir, sfDir) + + metricsFetcher := metric.NewFakeMetricsFetcher(metrics.DummyMetrics{}) + metaCache, err := metacache.NewMetaCacheImp(conf, metricspool.DummyMetricsEmitterPool{}, metricsFetcher) + require.NoError(t, err) + + for _, c := range tt.fields.containers { + err := metaCache.SetContainerInfo(c.PodUID, c.ContainerName, c) + assert.NoError(t, err) + } + + metaServer := generateTestMetaServer(t, tt.fields.podList, metricsFetcher) + + p := NewPolicyNUMAAware(conf, nil, metaCache, metaServer, metrics.DummyMetrics{}) + + store := metricsFetcher.(*metric.FakeMetricsFetcher) + tt.fields.setFakeMetric(store) + + p.SetEssentials(tt.fields.essentials) + + err = p.Update() + if (err != nil) != tt.wantErr { + t.Errorf("update() error = %v, wantErr %v", err, tt.wantErr) + return + } + got, err := p.GetHeadroom() + if (err != nil) != tt.wantErr { + t.Errorf("GetHeadroom() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got.MilliValue() != tt.want.MilliValue() { + t.Errorf("GetHeadroom() got = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/agent/sysadvisor/types/memory.go b/pkg/agent/sysadvisor/types/memory.go index fc85bb15a..357f9e352 100644 --- a/pkg/agent/sysadvisor/types/memory.go +++ b/pkg/agent/sysadvisor/types/memory.go @@ -35,6 +35,7 @@ const ( MemoryHeadroomPolicyNone MemoryHeadroomPolicyName = "none" MemoryHeadroomPolicyCanonical MemoryHeadroomPolicyName = "canonical" + MemoryHeadroomPolicyNUMAAware MemoryHeadroomPolicyName = "numa-aware" ) type MemoryPressureCondition struct { diff --git a/pkg/metaserver/agent/metric/malachite/fetcher.go b/pkg/metaserver/agent/metric/malachite/fetcher.go index 836788f64..b8a190db2 100644 --- a/pkg/metaserver/agent/metric/malachite/fetcher.go +++ b/pkg/metaserver/agent/metric/malachite/fetcher.go @@ -46,6 +46,8 @@ const ( metricsNamMalachiteUnHealthy = "malachite_unhealthy" metricsNameMalachiteGetSystemStatusFailed = "malachite_get_system_status_failed" metricsNameMalachiteGetPodStatusFailed = "malachite_get_pod_status_failed" + + pageShift = 12 ) // NewMalachiteMetricsFetcher returns the default implementation of MetricsFetcher. @@ -629,9 +631,9 @@ func (m *MalachiteMetricsFetcher) processCgroupPerNumaMemoryData(cgroupPath stri for _, data := range numaStats { numaID := strings.TrimPrefix(data.NumaName, "N") - m.metricStore.SetCgroupNumaMetric(cgroupPath, numaID, consts.MetricsMemTotalPerNumaCgroup, utilmetric.MetricData{Time: &updateTime, Value: float64(data.Total << 10)}) - m.metricStore.SetCgroupNumaMetric(cgroupPath, numaID, consts.MetricsMemFilePerNumaCgroup, utilmetric.MetricData{Time: &updateTime, Value: float64(data.File << 10)}) - m.metricStore.SetCgroupNumaMetric(cgroupPath, numaID, consts.MetricsMemAnonPerNumaCgroup, utilmetric.MetricData{Time: &updateTime, Value: float64(data.Anon << 10)}) + m.metricStore.SetCgroupNumaMetric(cgroupPath, numaID, consts.MetricsMemTotalPerNumaCgroup, utilmetric.MetricData{Time: &updateTime, Value: float64(data.Total << pageShift)}) + m.metricStore.SetCgroupNumaMetric(cgroupPath, numaID, consts.MetricsMemFilePerNumaCgroup, utilmetric.MetricData{Time: &updateTime, Value: float64(data.File << pageShift)}) + m.metricStore.SetCgroupNumaMetric(cgroupPath, numaID, consts.MetricsMemAnonPerNumaCgroup, utilmetric.MetricData{Time: &updateTime, Value: float64(data.Anon << pageShift)}) } } else if cgStats.CgroupType == "V2" { numaStats := cgStats.V2.Memory.MemNumaStats @@ -640,9 +642,9 @@ func (m *MalachiteMetricsFetcher) processCgroupPerNumaMemoryData(cgroupPath stri for numa, data := range numaStats { numaID := strings.TrimPrefix(numa, "N") total := data.Anon + data.File + data.Unevictable - m.metricStore.SetCgroupNumaMetric(cgroupPath, numaID, consts.MetricsMemTotalPerNumaCgroup, utilmetric.MetricData{Time: &updateTime, Value: float64(total << 10)}) - m.metricStore.SetCgroupNumaMetric(cgroupPath, numaID, consts.MetricsMemFilePerNumaCgroup, utilmetric.MetricData{Time: &updateTime, Value: float64(data.File << 10)}) - m.metricStore.SetCgroupNumaMetric(cgroupPath, numaID, consts.MetricsMemAnonPerNumaCgroup, utilmetric.MetricData{Time: &updateTime, Value: float64(data.Anon << 10)}) + m.metricStore.SetCgroupNumaMetric(cgroupPath, numaID, consts.MetricsMemTotalPerNumaCgroup, utilmetric.MetricData{Time: &updateTime, Value: float64(total << pageShift)}) + m.metricStore.SetCgroupNumaMetric(cgroupPath, numaID, consts.MetricsMemFilePerNumaCgroup, utilmetric.MetricData{Time: &updateTime, Value: float64(data.File << pageShift)}) + m.metricStore.SetCgroupNumaMetric(cgroupPath, numaID, consts.MetricsMemAnonPerNumaCgroup, utilmetric.MetricData{Time: &updateTime, Value: float64(data.Anon << pageShift)}) } } } @@ -919,11 +921,11 @@ func (m *MalachiteMetricsFetcher) processContainerPerNumaMemoryData(podUID, cont for _, data := range numaStats { numaID := strings.TrimPrefix(data.NumaName, "N") m.metricStore.SetContainerNumaMetric(podUID, containerName, numaID, consts.MetricsMemTotalPerNumaContainer, - utilmetric.MetricData{Value: float64(data.Total << 10), Time: &updateTime}) + utilmetric.MetricData{Value: float64(data.Total << pageShift), Time: &updateTime}) m.metricStore.SetContainerNumaMetric(podUID, containerName, numaID, consts.MetricsMemFilePerNumaContainer, - utilmetric.MetricData{Value: float64(data.File << 10), Time: &updateTime}) + utilmetric.MetricData{Value: float64(data.File << pageShift), Time: &updateTime}) m.metricStore.SetContainerNumaMetric(podUID, containerName, numaID, consts.MetricsMemAnonPerNumaContainer, - utilmetric.MetricData{Value: float64(data.Anon << 10), Time: &updateTime}) + utilmetric.MetricData{Value: float64(data.Anon << pageShift), Time: &updateTime}) } } else if cgStats.CgroupType == "V2" { numaStats := cgStats.V2.Memory.MemNumaStats @@ -933,11 +935,11 @@ func (m *MalachiteMetricsFetcher) processContainerPerNumaMemoryData(podUID, cont numaID := strings.TrimPrefix(numa, "N") total := data.Anon + data.File + data.Unevictable m.metricStore.SetContainerNumaMetric(podUID, containerName, numaID, consts.MetricsMemTotalPerNumaContainer, - utilmetric.MetricData{Value: float64(total << 10), Time: &updateTime}) + utilmetric.MetricData{Value: float64(total << pageShift), Time: &updateTime}) m.metricStore.SetContainerNumaMetric(podUID, containerName, numaID, consts.MetricsMemFilePerNumaContainer, - utilmetric.MetricData{Value: float64(data.File << 10), Time: &updateTime}) + utilmetric.MetricData{Value: float64(data.File << pageShift), Time: &updateTime}) m.metricStore.SetContainerNumaMetric(podUID, containerName, numaID, consts.MetricsMemAnonPerNumaContainer, - utilmetric.MetricData{Value: float64(data.Anon << 10), Time: &updateTime}) + utilmetric.MetricData{Value: float64(data.Anon << pageShift), Time: &updateTime}) } } }