From c2dfcaf0df0cf879cbfabc0cee67c370b06673c9 Mon Sep 17 00:00:00 2001 From: Jonathan Innis Date: Thu, 30 Jan 2025 15:41:56 -0800 Subject: [PATCH] Don't create new sets when checking compatability --- pkg/scheduling/requirement.go | 40 ++++++++++++++++++++++++++++++++++ pkg/scheduling/requirements.go | 3 +-- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/pkg/scheduling/requirement.go b/pkg/scheduling/requirement.go index a491baaab6..81c266206a 100644 --- a/pkg/scheduling/requirement.go +++ b/pkg/scheduling/requirement.go @@ -187,6 +187,46 @@ func (r *Requirement) Intersection(requirement *Requirement) *Requirement { return &Requirement{Key: r.Key, values: values, complement: complement, greaterThan: greaterThan, lessThan: lessThan, MinValues: minValues} } +// nolint:gocyclo +// HasIntersection is a more efficient implementation of Intersection +// It validates whether there is an intersection between the two requirements without actually creating the sets +// This prevents the garbage collector from having to spend cycles cleaning up all of these created set objects +func (r *Requirement) HasIntersection(requirement *Requirement) bool { + greaterThan := maxIntPtr(r.greaterThan, requirement.greaterThan) + lessThan := minIntPtr(r.lessThan, requirement.lessThan) + if greaterThan != nil && lessThan != nil && *greaterThan >= *lessThan { + return false + } + // Both requirements have a complement + if r.complement && requirement.complement { + return true + } + // Only one requirement has a complement + if r.complement && !requirement.complement { + for value := range requirement.values { + if !r.values.Has(value) && withinIntPtrs(value, greaterThan, lessThan) { + return true + } + } + return false + } + if !r.complement && requirement.complement { + for value := range r.values { + if !requirement.values.Has(value) && withinIntPtrs(value, greaterThan, lessThan) { + return true + } + } + return false + } + // Both requirements are non-complement requirements + for value := range r.values { + if requirement.values.Has(value) && withinIntPtrs(value, greaterThan, lessThan) { + return true + } + } + return false +} + func (r *Requirement) Any() string { switch r.Operator() { case corev1.NodeSelectorOpIn: diff --git a/pkg/scheduling/requirements.go b/pkg/scheduling/requirements.go index 87c36179c4..4f32f417a7 100644 --- a/pkg/scheduling/requirements.go +++ b/pkg/scheduling/requirements.go @@ -284,8 +284,7 @@ func (r Requirements) Intersects(requirements Requirements) (errs error) { for key := range r.intersectKeys(requirements) { existing := r.Get(key) incoming := requirements.Get(key) - // There must be some value, except - if existing.Intersection(incoming).Len() == 0 { + if !existing.HasIntersection(incoming) { // where the incoming requirement has operator { NotIn, DoesNotExist } if operator := incoming.Operator(); operator == corev1.NodeSelectorOpNotIn || operator == corev1.NodeSelectorOpDoesNotExist { // and the existing requirement has operator { NotIn, DoesNotExist }