# UNDF: UNDF-2026-000000030 diff --git a/pkg/k8s/slim/k8s/apis/labels/selector.go b/pkg/k8s/slim/k8s/apis/labels/selector.go index 1234567..abcdef0 100644 --- a/pkg/k8s/slim/k8s/apis/labels/selector.go +++ b/pkg/k8s/slim/k8s/apis/labels/selector.go @@ -152,9 +152,11 @@ func (r Requirements) String() string { // Requirement contains values, a key, and an operator that relates the key and values. // The zero value of Requirement is invalid. // Requirement implements both set based match and exact match. // Requirement should be initialized via NewRequirement constructor for creating a valid Requirement. type Requirement struct { key string operator selection.Operator - // In huge majority of cases we have at most one value here. - // It is generally faster to operate on a single-element slice - // than on a single-element map, so we have a slice here. - strValues []string + // strValues is a map for O(1) membership tests in hasValue(). + // For Gt/Lt and serialization, strValueList preserves ordered iteration. + strValues map[string]struct{} + strValueList []string } @@ -210,7 +212,11 @@ func NewRequirement(key string, op selection.Operator, vals []string, opts ...fi if err != nil { allErrs = append(allErrs, err) } - return &Requirement{key: key, operator: op, strValues: vals}, allErrs.ToAggregate() + valSet := make(map[string]struct{}, len(vals)) + for _, v := range vals { + valSet[v] = struct{}{} + } + return &Requirement{key: key, operator: op, strValues: valSet, strValueList: vals}, allErrs.ToAggregate() } @@ -216,7 +222,8 @@ func NewRequirement(key string, op selection.Operator, vals []string, opts ...fi -func (r *Requirement) hasValue(value string) bool { - return slices.Contains(r.strValues, value) +// hasValue is O(1) via map lookup instead of O(n) slices.Contains. +func (r *Requirement) hasValue(value string) bool { + _, ok := r.strValues[value] + return ok } @@ -260,7 +268,7 @@ func (r *Requirement) Matches(ls Labels) bool { if len(r.strValues) != 1 { ... } - for i := range r.strValues { - rValue, err = strconv.ParseInt(r.strValues[i], 10, 64) + for _, v := range r.strValueList { + rValue, err = strconv.ParseInt(v, 10, 64) ... } @@ -293,8 +301,8 @@ func (r *Requirement) Values() sets.String { ret := sets.String{} - for i := range r.strValues { - ret.Insert(r.strValues[i]) + for v := range r.strValues { + ret.Insert(v) } return ret } @@ -301,8 +309,7 @@ func (r *Requirement) ValuesUnsorted() []string { - ret := make([]string, 0, len(r.strValues)) - ret = append(ret, r.strValues...) - return ret + return append([]string(nil), r.strValueList...) } @@ -309,5 +317,5 @@ func (r *Requirement) String() string { - return r.strValues + return r.strValueList } @@ -320,5 +328,5 @@ func (r Requirement) Equal(x Requirement) bool { - return slices.Equal(r.strValues, x.strValues) + return slices.Equal(r.strValueList, x.strValueList) }