github.com/kubewharf/katalyst-core@v0.5.3/pkg/agent/sysadvisor/plugin/qosaware/resource/cpu/assembler/headroomassembler/assembler_dedicated.go (about) 1 /* 2 Copyright 2022 The Katalyst Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package headroomassembler 18 19 import ( 20 "fmt" 21 22 v1 "k8s.io/api/core/v1" 23 "k8s.io/apimachinery/pkg/api/resource" 24 "k8s.io/klog/v2" 25 26 "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/cpu/dynamicpolicy/state" 27 "github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/metacache" 28 "github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/plugin/qosaware/resource/cpu/region" 29 "github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/types" 30 "github.com/kubewharf/katalyst-core/pkg/config" 31 "github.com/kubewharf/katalyst-core/pkg/metaserver" 32 "github.com/kubewharf/katalyst-core/pkg/metrics" 33 "github.com/kubewharf/katalyst-core/pkg/util/machine" 34 ) 35 36 type HeadroomAssemblerDedicated struct { 37 conf *config.Configuration 38 regionMap *map[string]region.QoSRegion 39 reservedForReclaim *map[int]int 40 numaAvailable *map[int]int 41 nonBindingNumas *machine.CPUSet 42 43 metaReader metacache.MetaReader 44 metaServer *metaserver.MetaServer 45 emitter metrics.MetricEmitter 46 } 47 48 func NewHeadroomAssemblerDedicated(conf *config.Configuration, _ interface{}, regionMap *map[string]region.QoSRegion, 49 reservedForReclaim *map[int]int, numaAvailable *map[int]int, nonBindingNumas *machine.CPUSet, 50 metaReader metacache.MetaReader, metaServer *metaserver.MetaServer, emitter metrics.MetricEmitter, 51 ) HeadroomAssembler { 52 return &HeadroomAssemblerDedicated{ 53 conf: conf, 54 regionMap: regionMap, 55 reservedForReclaim: reservedForReclaim, 56 numaAvailable: numaAvailable, 57 nonBindingNumas: nonBindingNumas, 58 59 metaReader: metaReader, 60 metaServer: metaServer, 61 emitter: emitter, 62 } 63 } 64 65 func (ha *HeadroomAssemblerDedicated) GetHeadroom() (resource.Quantity, error) { 66 dynamicConfig := ha.conf.GetDynamicConfiguration() 67 reserved := ha.conf.GetDynamicConfiguration().ReservedResourceForAllocate[v1.ResourceCPU] 68 69 // return zero when reclaim is disabled 70 if !dynamicConfig.EnableReclaim { 71 return *resource.NewQuantity(0, resource.DecimalSI), nil 72 } 73 74 headroomTotal := 0.0 75 emptyNUMAs := ha.metaServer.CPUDetails.NUMANodes() 76 exclusiveNUMAs := machine.NewCPUSet() 77 78 // sum up dedicated region headroom 79 for _, r := range *ha.regionMap { 80 if r.Type() == types.QoSRegionTypeDedicatedNumaExclusive { 81 regionInfo, ok := ha.metaReader.GetRegionInfo(r.Name()) 82 if !ok || regionInfo == nil || regionInfo.Headroom < 0 { 83 return resource.Quantity{}, fmt.Errorf("failed to get headroom for %v", r.Name()) 84 } 85 headroomTotal += regionInfo.Headroom 86 exclusiveNUMAs = exclusiveNUMAs.Union(r.GetBindingNumas()) 87 88 klog.InfoS("dedicated NUMA headroom", "headroom", regionInfo.Headroom, "NUMAs", r.GetBindingNumas().String()) 89 } 90 emptyNUMAs = emptyNUMAs.Difference(r.GetBindingNumas()) 91 } 92 93 // add non binding reclaim pool size 94 reclaimPoolInfo, ok := ha.metaReader.GetPoolInfo(state.PoolNameReclaim) 95 if ok && reclaimPoolInfo != nil { 96 reclaimPoolNUMAs := machine.GetCPUAssignmentNUMAs(reclaimPoolInfo.TopologyAwareAssignments) 97 for _, numaID := range reclaimPoolNUMAs.Difference(exclusiveNUMAs).Difference(emptyNUMAs).ToSliceInt() { 98 headroom := float64(reclaimPoolInfo.TopologyAwareAssignments[numaID].Size()) 99 headroomTotal += headroom 100 101 klog.InfoS("reclaim pool headroom", "headroom", headroom, "numaID", numaID) 102 } 103 } 104 105 // add empty numa headroom 106 for _, numaID := range emptyNUMAs.ToSliceInt() { 107 available, _ := (*ha.numaAvailable)[numaID] 108 reservedForAllocate := float64(reserved.Value()*int64(emptyNUMAs.Size())) / float64(ha.metaServer.NumNUMANodes) 109 reservedForReclaim, _ := (*ha.reservedForReclaim)[numaID] 110 headroom := float64(available) - reservedForAllocate + float64(reservedForReclaim) 111 headroomTotal += headroom 112 113 klog.InfoS("empty NUMA headroom", "headroom", headroom) 114 } 115 116 klog.Infof("[qosaware-cpu] total headroom assembled %.2f", headroomTotal) 117 118 return *resource.NewQuantity(int64(headroomTotal), resource.DecimalSI), nil 119 }