Skip to content

Optimize sets.Set #133231

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions pkg/apis/resource/validation/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -419,9 +419,9 @@ func validateResourceClaimStatusUpdate(status, oldStatus *resource.ResourceClaim
if claimDeleted {
oldSet := sets.New(oldStatus.ReservedFor...)
newSet := sets.New(status.ReservedFor...)
newItems := newSet.Difference(oldSet)
if len(newItems) > 0 {
for range newSet.DifferenceSeq(oldSet) {
allErrs = append(allErrs, field.Forbidden(fldPath.Child("reservedFor"), "new entries may not be added while `deallocationRequested` or `deletionTimestamp` are set"))
break // only need to check if there is at least one item
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/controller/podautoscaler/replica_calculator.go
Original file line number Diff line number Diff line change
Expand Up @@ -523,7 +523,7 @@ func calculatePodRequestsFromContainers(pod *v1.Pod, container string, resource
}

func removeMetricsForPods(metrics metricsclient.PodMetricsInfo, pods sets.Set[string]) {
for _, pod := range pods.UnsortedList() {
for pod := range pods {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can iterate the set directly, no need to make a copy.

delete(metrics, pod)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ func (c *Controller) syncPod(ctx context.Context, pod *v1.Pod) error {
}

mounts, _, seLinuxLabels := volumeutil.GetPodVolumeNames(pod, true /* collectSELinuxOptions */)
for _, mount := range mounts.UnsortedList() {
for mount := range mounts {
opts := seLinuxLabels[mount]
spec, found := volumeSpecs[mount]
if !found {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -368,8 +368,8 @@ func (c *Controller) pvcUpdated(logger klog.Logger, old, new interface{}) {

logger.V(4).Info("Got event on PVC", "PVC", klog.KObj(newPVC))

vavNames := sets.New(getPVCReferencedVACNames(oldPVC)...).Delete(getPVCReferencedVACNames(newPVC)...).UnsortedList()
for _, vacName := range vavNames {
vavNames := sets.New(getPVCReferencedVACNames(oldPVC)...).Delete(getPVCReferencedVACNames(newPVC)...)
for vacName := range vavNames {
c.queue.Add(vacName)
}
}
Expand All @@ -388,8 +388,8 @@ func (c *Controller) pvUpdated(logger klog.Logger, old, new interface{}) {
}

logger.V(4).Info("Got event on PV", "PV", klog.KObj(newPV))
vavNames := sets.New(getPVReferencedVACNames(oldPV)...).Delete(getPVReferencedVACNames(newPV)...).UnsortedList()
for _, vacName := range vavNames {
vavNames := sets.New(getPVReferencedVACNames(oldPV)...).Delete(getPVReferencedVACNames(newPV)...)
for vacName := range vavNames {
c.queue.Add(vacName)
}
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/kubelet/cm/devicemanager/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -642,7 +642,7 @@ func (m *ManagerImpl) devicesToAllocate(podUID, contName, resource string, requi
if m.allocatedDevices[resource] == nil {
m.allocatedDevices[resource] = sets.New[string]()
}
for device := range devices.Difference(allocated) {
for device := range devices.DifferenceSeq(allocated) {
m.allocatedDevices[resource].Insert(device)
allocated.Insert(device)
needed--
Expand Down
2 changes: 1 addition & 1 deletion pkg/kubelet/cm/dra/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -956,7 +956,7 @@ func (m *Manager) HandleWatchResourcesStream(ctx context.Context, stream draheal
if driverState, ok := cInfo.DriverState[pluginName]; ok {
for _, allocatedDevice := range driverState.Devices {
if allocatedDevice.PoolName == dev.PoolName && allocatedDevice.DeviceName == dev.DeviceName {
podsToUpdate.Insert(cInfo.PodUIDs.UnsortedList()...)
podsToUpdate.InsertSet(cInfo.PodUIDs)
break
}
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/kubelet/images/pullmanager/image_pull_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ func (f *PullManager) initialize(ctx context.Context) {
for _, imageObj := range imageObjs {
existingRecordedImages := searchForExistingTagDigest(inFlightPulls, imageObj)

for _, image := range existingRecordedImages.UnsortedList() {
for image := range existingRecordedImages {

if err := f.writePulledRecordIfChanged(image, imageObj.ID, nil); err != nil {
klog.ErrorS(err, "failed to write an image pull record", "imageRef", imageObj.ID)
Expand Down
2 changes: 1 addition & 1 deletion pkg/kubelet/podcertificate/podcertificatemanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ func (m *IssuingManager) handleProjection(ctx context.Context, key projectionKey
// remember creating the PCR, then we must be in case 2. Return to
// credStateInitial so we create a new PCR.
rec.curState = &credStateInitial{}
return fmt.Errorf("PodCertificateRequest %q appears to have been deleted", pcr.ObjectMeta.Namespace+"/"+pcr.ObjectMeta.Name)
return fmt.Errorf("PodCertificateRequest %q appears to have been deleted", key.Namespace+"/"+state.pcrName)
} else if err != nil {
return fmt.Errorf("while getting PodCertificateRequest %q: %w", key.Namespace+"/"+state.pcrName, err)
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/kubelet/volumemanager/volume_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ func (vm *volumeManager) GetExtraSupplementalGroupsForPod(pod *v1.Pod) []int64 {
}

result := make([]int64, 0, supplementalGroups.Len())
for _, group := range supplementalGroups.UnsortedList() {
for group := range supplementalGroups {
iGroup, extra := getExtraSupplementalGID(group, pod)
if !extra {
continue
Expand Down
9 changes: 3 additions & 6 deletions pkg/proxy/ipvs/ipset.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,14 +157,11 @@ func (set *IPSet) syncIPSetEntries() {
}

// currentIPSetEntries represents Endpoints watched from API Server.
currentIPSetEntries := sets.New[string]()
for _, appliedEntry := range appliedEntries {
currentIPSetEntries.Insert(appliedEntry)
}
currentIPSetEntries := sets.New(appliedEntries...)

if !set.activeEntries.Equal(currentIPSetEntries) {
// Clean legacy entries
for _, entry := range currentIPSetEntries.Difference(set.activeEntries).UnsortedList() {
for entry := range currentIPSetEntries.DifferenceSeq(set.activeEntries) {
if err := set.handle.DelEntry(entry, set.Name); err != nil {
if !utilipset.IsNotFoundError(err) {
klog.ErrorS(err, "Failed to delete ip set entry from ip set", "ipSetEntry", entry, "ipSet", set.Name)
Expand All @@ -174,7 +171,7 @@ func (set *IPSet) syncIPSetEntries() {
}
}
// Create active entries
for _, entry := range set.activeEntries.Difference(currentIPSetEntries).UnsortedList() {
for entry := range set.activeEntries.DifferenceSeq(currentIPSetEntries) {
if err := set.handle.AddEntry(entry, &set.IPSet, true); err != nil {
klog.ErrorS(err, "Failed to add ip set entry to ip set", "ipSetEntry", entry, "ipSet", set.Name)
} else {
Expand Down
4 changes: 2 additions & 2 deletions pkg/proxy/ipvs/proxier.go
Original file line number Diff line number Diff line change
Expand Up @@ -1843,7 +1843,7 @@ func (proxier *Proxier) syncEndpoint(svcPortName proxy.ServicePortName, onlyNode
}

// Create new endpoints
for _, ep := range newEndpoints.UnsortedList() {
for ep := range newEndpoints {
ip, port, err := net.SplitHostPort(ep)
if err != nil {
proxier.logger.Error(err, "Failed to parse endpoint", "endpoint", ep)
Expand Down Expand Up @@ -1895,7 +1895,7 @@ func (proxier *Proxier) syncEndpoint(svcPortName proxy.ServicePortName, onlyNode
}

// Delete old endpoints
for _, ep := range curEndpoints.Difference(newEndpoints).UnsortedList() {
for ep := range curEndpoints.DifferenceSeq(newEndpoints) {
// if curEndpoint is in gracefulDelete, skip
uniqueRS := vs.String() + "/" + ep
if proxier.gracefuldeleteManager.InTerminationList(uniqueRS) {
Expand Down
35 changes: 27 additions & 8 deletions staging/src/k8s.io/apimachinery/pkg/util/sets/set.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ package sets

import (
"cmp"
"iter"
"maps"
"sort"
)

Expand Down Expand Up @@ -53,6 +55,13 @@ func (s Set[T]) Insert(items ...T) Set[T] {
return s
}

// InsertSet adds items to the set.
func (s Set[T]) InsertSet(items Set[T]) {
for item := range items {
s[item] = Empty{}
}
}

func Insert[T comparable](set Set[T], items ...T) Set[T] {
return set.Insert(items...)
}
Expand Down Expand Up @@ -101,11 +110,23 @@ func (s Set[T]) HasAny(items ...T) bool {

// Clone returns a new set which is a copy of the current set.
func (s Set[T]) Clone() Set[T] {
result := make(Set[T], len(s))
for key := range s {
result.Insert(key)
if s == nil {
return Set[T]{}
}
return maps.Clone(s)
}

// DifferenceSeq is an iterator version of Difference.
func (s1 Set[T]) DifferenceSeq(s2 Set[T]) iter.Seq[T] {
return func(yield func(T) bool) {
for key := range s1 {
if !s2.Has(key) {
if !yield(key) {
return
}
}
}
}
return result
}

// Difference returns a set of objects that are not in s2.
Expand All @@ -116,10 +137,8 @@ func (s Set[T]) Clone() Set[T] {
// s2.Difference(s1) = {a4, a5}
func (s1 Set[T]) Difference(s2 Set[T]) Set[T] {
result := New[T]()
for key := range s1 {
if !s2.Has(key) {
result.Insert(key)
}
for key := range s1.DifferenceSeq(s2) {
result.Insert(key)
}
return result
}
Expand Down
69 changes: 69 additions & 0 deletions staging/src/k8s.io/apimachinery/pkg/util/sets/set_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,57 @@ func TestStringIntersection(t *testing.T) {
}
}

func TestInsertSet(t *testing.T) {
s1 := New("1")
s2 := New("2")
s1.InsertSet(s2)

if s1.Len() != 2 {
t.Errorf("Expected Len()=2 but got %d", s1.Len())
}
if !s1.Has("1") {
t.Error(`Expected Has("1") to be true`)
}
if !s1.Has("2") {
t.Error(`Expected Has("2") to be true`)
}
}

func TestClone(t *testing.T) {
t.Run("nil", func(t *testing.T) {
var s Set[string]

c := s.Clone()

if c == nil {
t.Error("Clone returned nil")
}
if c.Len() != 0 {
t.Error("Clone returned non-zero length")
}
})
t.Run("empty", func(t *testing.T) {
s := Set[string]{}
c := s.Clone()

if c.Len() != 0 {
t.Error("Clone returned non-zero length")
}
})
t.Run("non-empty", func(t *testing.T) {
s := Set[string]{}
s.Insert("1")
c := s.Clone()

if c.Len() != 1 {
t.Errorf("Clone returned len %d", c.Len())
}
if !c.Has("1") {
t.Error("Expected '1' to be present")
}
})
}

type randomStringAlphabet string

func (a randomStringAlphabet) makeString(minLen, maxLen int) string {
Expand Down Expand Up @@ -369,5 +420,23 @@ func BenchmarkStringSet(b *testing.B) {
randOperand().List()
}
})
b.Run(fmt.Sprintf("difference-%v", here.size), func(b *testing.B) {
b.ReportAllocs()
for b.Loop() {
for item := range randOperand().Difference(randOperand()) {
_ = item
}
}
})
b.Run(fmt.Sprintf("difference-seq-%v", here.size), func(b *testing.B) {
b.ReportAllocs()
for b.Loop() {
s1 := Set[string](randOperand())
s2 := Set[string](randOperand())
for item := range s1.DifferenceSeq(s2) {
_ = item
}
}
})
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ func (s *ValidationTestBuilder) ValidateFixtures() {
}
})
}
for unexpectedType := range gotKeys.Difference(expectedKeys) {
for unexpectedType := range gotKeys.DifferenceSeq(expectedKeys) {
s.T.Run(unexpectedType, func(t *testing.T) {
t.Helper()

Expand Down Expand Up @@ -492,7 +492,7 @@ func (v *ValidationTester) expectInvalid(matcher matcher, errs ...*field.Error)
if !got.Equal(want) {
t.Errorf("validation errors differed from expected:\n%v\n", cmp.Diff(want, got, cmpopts.SortMaps(stdcmp.Less[string])))

for x := range got.Difference(want) {
for x := range got.DifferenceSeq(want) {
fmt.Printf("%q,\n", strings.TrimPrefix(x, "forced failure: "))
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,7 @@ func (t *Tracker) deviceTaintUpdate(ctx context.Context) func(oldObj, newObj any
slicesToSync := sets.New[string]()
slicesToSync.Insert(t.sliceNamesForPatch(ctx, oldPatch)...)
slicesToSync.Insert(t.sliceNamesForPatch(ctx, newPatch)...)
for _, sliceName := range slicesToSync.UnsortedList() {
for sliceName := range slicesToSync {
t.syncSlice(ctx, sliceName, false)
}
}
Expand Down
8 changes: 4 additions & 4 deletions staging/src/k8s.io/endpointslice/reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,7 @@ func (r *Reconciler) reconcileByPortMapping(
// iterate through the slices and fill them up with the desired endpoints.
if desiredSet.Len() > 0 && sliceNamesToUpdate.Len() > 0 {
slices := []*discovery.EndpointSlice{}
for _, sliceName := range sliceNamesToUpdate.UnsortedList() {
for sliceName := range sliceNamesToUpdate {
slices = append(slices, slicesByName[sliceName])
}
// Sort endpoint slices by length so we're filling up the fullest ones
Expand Down Expand Up @@ -601,7 +601,7 @@ func (r *Reconciler) reconcileByPortMapping(
// filled, try to fit them in one.
if desiredSet.Len() < int(r.maxEndpointsPerSlice) && sliceNamesUnchanged.Len() > 0 {
unchangedSlices := []*discovery.EndpointSlice{}
for _, sliceName := range sliceNamesUnchanged.UnsortedList() {
for sliceName := range sliceNamesUnchanged {
unchangedSlices = append(unchangedSlices, slicesByName[sliceName])
}
sliceToFill = getSliceToFill(unchangedSlices, desiredSet.Len(), int(r.maxEndpointsPerSlice))
Expand Down Expand Up @@ -634,13 +634,13 @@ func (r *Reconciler) reconcileByPortMapping(

// Build slicesToUpdate from slice names.
slicesToUpdate := []*discovery.EndpointSlice{}
for _, sliceName := range sliceNamesToUpdate.UnsortedList() {
for sliceName := range sliceNamesToUpdate {
slicesToUpdate = append(slicesToUpdate, slicesByName[sliceName])
}

// Build slicesToDelete from slice names.
slicesToDelete := []*discovery.EndpointSlice{}
for _, sliceName := range sliceNamesToDelete.UnsortedList() {
for sliceName := range sliceNamesToDelete {
slicesToDelete = append(slicesToDelete, slicesByName[sliceName])
}

Expand Down
2 changes: 1 addition & 1 deletion staging/src/k8s.io/kubectl/pkg/cmd/edit/edit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ func TestEdit(t *testing.T) {
t.Fatalf("Error locating edit testcases")
}

for _, testcaseName := range testcases.UnsortedList() {
for testcaseName := range testcases {
t.Run(testcaseName, func(t *testing.T) {
i = 0
name = testcaseName
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/storage/testsuites/volumelimits.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ func (t *volumeLimitsTestSuite) DefineTests(driver storageframework.TestDriver,
// just after the test ends.
err := wait.PollUntilContextTimeout(ctx, 5*time.Second, timeout, false, func(ctx context.Context) (bool, error) {
existing := 0
for _, pvName := range l.pvNames.UnsortedList() {
for pvName := range l.pvNames {
_, err := l.cs.CoreV1().PersistentVolumes().Get(ctx, pvName, metav1.GetOptions{})
if err == nil {
existing++
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ func RunAuthzSelectorsLibraryTests(t *testing.T, featureEnabled bool) {
actualCauses := getCauses(t, err)
for _, expectCause := range expectedErrors {
found := false
for _, cause := range actualCauses.UnsortedList() {
for cause := range actualCauses {
if expectCause.MatchString(cause) {
actualCauses.Delete(cause)
found = true
Expand Down