From 2eec3831c1adce5a9057de65ef3d0b9967b73051 Mon Sep 17 00:00:00 2001 From: Krisztian Litkey Date: Wed, 4 Dec 2024 19:28:35 +0200 Subject: [PATCH] topology-aware: add prefer-shared-partial-llc-group annotation. Add an annotation to indicate a CPU allocation preference with the last/partial LLC group shared instead of using an idle one. The full annotation syntax is metadata: annotations: prefer-shared-partial-llc-group.resource-policy.nri.io: "true" Signed-off-by: Krisztian Litkey --- .../topology-aware/policy/pod-preferences.go | 17 +++++++++++++++++ cmd/plugins/topology-aware/policy/resources.go | 14 ++++++++++---- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/cmd/plugins/topology-aware/policy/pod-preferences.go b/cmd/plugins/topology-aware/policy/pod-preferences.go index 9a0d1a32c..561754066 100644 --- a/cmd/plugins/topology-aware/policy/pod-preferences.go +++ b/cmd/plugins/topology-aware/policy/pod-preferences.go @@ -47,6 +47,8 @@ const ( keyCpuPriorityPreference = "prefer-cpu-priority" // annotation key for hiding hyperthreads from allocated CPU sets keyHideHyperthreads = "hide-hyperthreads" + // annotation to prefer shared LLC groups for the last (but not first) partial one + keyPreferSharedPartialLLCGroup = "prefer-shared-parital-llc-group" // effective annotation key for isolated CPU preference preferIsolatedCPUsKey = keyIsolationPreference + "." + kubernetes.ResmgrKeyNamespace @@ -62,6 +64,8 @@ const ( preferCpuPriorityKey = keyCpuPriorityPreference + "." + kubernetes.ResmgrKeyNamespace // effective annotation key for hiding hyperthreads hideHyperthreadsKey = keyHideHyperthreads + "." + kubernetes.ResmgrKeyNamespace + // effective annotation key for shared partial LLC groups preference + preferSharedPartialLLCGroupKey = keyPreferSharedPartialLLCGroup + "." + kubernetes.ResmgrKeyNamespace ) // cpuClass is a type of CPU to allocate @@ -198,6 +202,19 @@ func hideHyperthreadsPreference(pod cache.Pod, container cache.Container) bool { return hide } +// sharedPartialLLCGroupPreference returns whether a container prefers shared partial LLC groups. +func sharedPartialLLCGroupPreference(container cache.Container) bool { + value, ok := container.GetEffectiveAnnotation(preferSharedPartialLLCGroupKey) + if !ok { + return false + } + shared, err := strconv.ParseBool(value) + if err != nil { + return false + } + return shared +} + // memoryTypePreference returns what type of memory should be allocated for the container. // // If the effective annotations are not found, this function falls back to diff --git a/cmd/plugins/topology-aware/policy/resources.go b/cmd/plugins/topology-aware/policy/resources.go index 52c739605..fbb990f4f 100644 --- a/cmd/plugins/topology-aware/policy/resources.go +++ b/cmd/plugins/topology-aware/policy/resources.go @@ -403,9 +403,15 @@ func (cs *supply) AllocateCPU(r Request) (Grant, error) { } // allocate isolated exclusive CPUs or slice them off the sharable set + allocFlags := cpuallocator.AllocDefault + if sharedPartialLLCGroupPreference(cr.GetContainer()) { + log.Info("using shared LLC group preference for %s", cr.GetContainer().PrettyName()) + allocFlags |= cpuallocator.PreferPartialSharedGroups + } + switch { case full > 0 && cs.isolated.Size() >= full && cr.isolate: - exclusive, err = cs.takeCPUs(&cs.isolated, nil, full, cr.CPUPrio()) + exclusive, err = cs.takeCPUs(&cs.isolated, nil, full, cr.CPUPrio().Option(), cpuallocator.WithAllocFlags(allocFlags)) if err != nil { return nil, policyError("internal error: "+ "%s: can't take %d exclusive isolated CPUs from %s: %v", @@ -413,7 +419,7 @@ func (cs *supply) AllocateCPU(r Request) (Grant, error) { } case full > 0 && cs.AllocatableSharedCPU() > 1000*full: - exclusive, err = cs.takeCPUs(&cs.sharable, nil, full, cr.CPUPrio()) + exclusive, err = cs.takeCPUs(&cs.sharable, nil, full, cr.CPUPrio().Option(), cpuallocator.WithAllocFlags(allocFlags)) if err != nil { return nil, policyError("internal error: "+ "%s: can't take %d exclusive CPUs from %s: %v", @@ -509,8 +515,8 @@ func (cs *supply) Reserve(g Grant, o *libmem.Offer) (map[string]libmem.NodeMask, } // takeCPUs takes up to cnt CPUs from a given CPU set to another. -func (cs *supply) takeCPUs(from, to *cpuset.CPUSet, cnt int, prio cpuPrio) (cpuset.CPUSet, error) { - cset, err := cs.node.Policy().cpuAllocator.AllocateCpus(from, cnt, prio.Option()) +func (cs *supply) takeCPUs(from, to *cpuset.CPUSet, cnt int, options ...cpuallocator.Option) (cpuset.CPUSet, error) { + cset, err := cs.node.Policy().cpuAllocator.AllocateCpus(from, cnt, options...) if err != nil { return cset, err }