Skip to content

Commit bd3b4a1

Browse files
committed
use slices.Compact to deduplicate topologyTerm
This allow us to get rid of the hash() func, which is slow and do too many allocations.
1 parent 5e854d9 commit bd3b4a1

File tree

2 files changed

+15
-69
lines changed

2 files changed

+15
-69
lines changed

pkg/controller/topology.go

Lines changed: 9 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,8 @@ func GenerateAccessibilityRequirements(
235235
return nil, nil
236236
}
237237

238-
requisiteTerms = deduplicate(requisiteTerms)
238+
slices.SortFunc(requisiteTerms, topologyTerm.compare)
239+
requisiteTerms = slices.CompactFunc(requisiteTerms, slices.Equal)
239240
// TODO (verult) reduce subset duplicate terms (advanced reduction)
240241

241242
requirement.Requisite = toCSITopology(requisiteTerms)
@@ -249,14 +250,19 @@ func GenerateAccessibilityRequirements(
249250
// requisiteTerms and shifting the sorted terms based on hash of pvcName and replica index suffix
250251
hash, index := getPVCNameHashAndIndexOffset(pvcName)
251252
i := (hash + index) % uint32(len(requisiteTerms))
252-
preferredTerms = sortAndShift(requisiteTerms, nil, i)
253+
preferredTerms = append(requisiteTerms[i:], requisiteTerms[:i]...)
253254
} else {
254255
// Delayed binding, use topology from that node to populate preferredTerms
255256
if strictTopology {
256257
// In case of strict topology, preferred = requisite
257258
preferredTerms = requisiteTerms
258259
} else {
259-
preferredTerms = sortAndShift(requisiteTerms, selectedTopology, 0)
260+
for i, t := range requisiteTerms {
261+
if t.subset(selectedTopology) {
262+
preferredTerms = append(requisiteTerms[i:], requisiteTerms[:i]...)
263+
break
264+
}
265+
}
260266
if preferredTerms == nil {
261267
// Topology from selected node is not in requisite. This case should never be hit:
262268
// - If AllowedTopologies is specified, the scheduler should choose a node satisfying the
@@ -447,38 +453,6 @@ func flatten(allowedTopologies []v1.TopologySelectorTerm) []topologyTerm {
447453
return finalTerms
448454
}
449455

450-
func deduplicate(terms []topologyTerm) []topologyTerm {
451-
termMap := make(map[string]topologyTerm)
452-
for _, term := range terms {
453-
termMap[term.hash()] = term
454-
}
455-
456-
var dedupedTerms []topologyTerm
457-
for _, term := range termMap {
458-
dedupedTerms = append(dedupedTerms, term)
459-
}
460-
return dedupedTerms
461-
}
462-
463-
// Sort the given terms in place,
464-
// then return a new list of terms equivalent to the sorted terms, but shifted so that
465-
// either the primary term (if specified) or term at shiftIndex is the first in the list.
466-
func sortAndShift(terms []topologyTerm, primary topologyTerm, shiftIndex uint32) []topologyTerm {
467-
var preferredTerms []topologyTerm
468-
slices.SortFunc(terms, topologyTerm.compare)
469-
if primary == nil {
470-
preferredTerms = append(terms[shiftIndex:], terms[:shiftIndex]...)
471-
} else {
472-
for i, t := range terms {
473-
if t.subset(primary) {
474-
preferredTerms = append(terms[i:], terms[:i]...)
475-
break
476-
}
477-
}
478-
}
479-
return preferredTerms
480-
}
481-
482456
func getTopologyKeys(csiNode *storagev1.CSINode, driverName string) []string {
483457
for _, driver := range csiNode.Spec.Drivers {
484458
if driver.Name == driverName {
@@ -533,24 +507,6 @@ func (t topologyTerm) sort() {
533507
})
534508
}
535509

536-
// "<k1>#<v1>,<k2>#<v2>,..."
537-
// Hash properties:
538-
// - Two equivalent topologyTerms have the same hash
539-
// - Ordering of hashes correspond to a natural ordering of their topologyTerms. For example:
540-
// - com.example.csi/zone#zone1 < com.example.csi/zone#zone2
541-
// - com.example.csi/rack#zz < com.example.csi/zone#zone1
542-
// - com.example.csi/z#z1 < com.example.csi/zone#zone1
543-
// - com.example.csi/rack#rackA,com.example.csi/zone#zone2 < com.example.csi/rackB,com.example.csi/zone#zone1
544-
// Note that both '#' and ',' are less than '/', '-', '_', '.', [A-Z0-9a-z]
545-
func (t topologyTerm) hash() string {
546-
var segments []string
547-
for _, k := range t {
548-
segments = append(segments, k.Key+"#"+k.Value)
549-
}
550-
551-
return strings.Join(segments, ",")
552-
}
553-
554510
func (t topologyTerm) compare(other topologyTerm) int {
555511
if len(t) != len(other) {
556512
return len(t) - len(other)

pkg/controller/topology_test.go

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1484,22 +1484,12 @@ func BenchmarkDedupAndSortHost(b *testing.B) {
14841484
}
14851485

14861486
func benchmarkDedupAndSort(b *testing.B, terms []topologyTerm) {
1487-
b.Run("slices.Sort", func(b *testing.B) {
1488-
for range b.N {
1489-
terms := slices.Clone(terms)
1490-
terms = deduplicate(terms)
1491-
slices.SortFunc(terms, topologyTerm.compare)
1492-
toCSITopology(terms)
1493-
}
1494-
})
1495-
b.Run("slices.Compact", func(b *testing.B) {
1496-
for range b.N {
1497-
terms := slices.Clone(terms)
1498-
slices.SortFunc(terms, topologyTerm.compare)
1499-
terms = slices.CompactFunc(terms, slices.Equal)
1500-
toCSITopology(terms)
1501-
}
1502-
})
1487+
for range b.N {
1488+
terms := slices.Clone(terms)
1489+
slices.SortFunc(terms, topologyTerm.compare)
1490+
terms = slices.CompactFunc(terms, slices.Equal)
1491+
toCSITopology(terms)
1492+
}
15031493
}
15041494

15051495
func buildNodes(nodeLabels []map[string]string) *v1.NodeList {

0 commit comments

Comments
 (0)