diff --git a/pkg/scheduler/framework/plugins/podtopologyspread/filtering.go b/pkg/scheduler/framework/plugins/podtopologyspread/filtering.go index 16cb2ca120b..9d716c3ee8f 100644 --- a/pkg/scheduler/framework/plugins/podtopologyspread/filtering.go +++ b/pkg/scheduler/framework/plugins/podtopologyspread/filtering.go @@ -20,12 +20,12 @@ import ( "context" "fmt" "math" - "sync" + "sync/atomic" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/klog" - pluginhelper "k8s.io/kubernetes/pkg/scheduler/framework/plugins/helper" + "k8s.io/kubernetes/pkg/scheduler/framework/plugins/helper" framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1" "k8s.io/kubernetes/pkg/scheduler/internal/parallelize" "k8s.io/kubernetes/pkg/scheduler/nodeinfo" @@ -48,7 +48,7 @@ type preFilterState struct { // it's not guaranteed to be the 2nd minimum match number. TpKeyToCriticalPaths map[string]*criticalPaths // TpPairToMatchNum is keyed with topologyPair, and valued with the number of matching pods. - TpPairToMatchNum map[topologyPair]int32 + TpPairToMatchNum map[topologyPair]*int32 } // Clone makes a copy of the given state. @@ -61,14 +61,15 @@ func (s *preFilterState) Clone() framework.StateData { // Constraints are shared because they don't change. Constraints: s.Constraints, TpKeyToCriticalPaths: make(map[string]*criticalPaths, len(s.TpKeyToCriticalPaths)), - TpPairToMatchNum: make(map[topologyPair]int32, len(s.TpPairToMatchNum)), + TpPairToMatchNum: make(map[topologyPair]*int32, len(s.TpPairToMatchNum)), } for tpKey, paths := range s.TpKeyToCriticalPaths { copy.TpKeyToCriticalPaths[tpKey] = &criticalPaths{paths[0], paths[1]} } for tpPair, matchNum := range s.TpPairToMatchNum { copyPair := topologyPair{key: tpPair.key, value: tpPair.value} - copy.TpPairToMatchNum[copyPair] = matchNum + copyCount := *matchNum + copy.TpPairToMatchNum[copyPair] = ©Count } return © } @@ -137,9 +138,9 @@ func (s *preFilterState) updateWithPod(updatedPod, preemptorPod *v1.Pod, node *v k, v := constraint.TopologyKey, node.Labels[constraint.TopologyKey] pair := topologyPair{key: k, value: v} - s.TpPairToMatchNum[pair] = s.TpPairToMatchNum[pair] + delta + *s.TpPairToMatchNum[pair] += delta - s.TpKeyToCriticalPaths[k].update(v, s.TpPairToMatchNum[pair]) + s.TpKeyToCriticalPaths[k].update(v, *s.TpPairToMatchNum[pair]) } } @@ -219,52 +220,44 @@ func (pl *PodTopologySpread) calPreFilterState(pod *v1.Pod) (*preFilterState, er return &preFilterState{}, nil } - var lock sync.Mutex - - // TODO(Huang-Wei): It might be possible to use "make(map[topologyPair]*int32)". - // In that case, need to consider how to init each tpPairToCount[pair] in an atomic fashion. s := preFilterState{ Constraints: constraints, TpKeyToCriticalPaths: make(map[string]*criticalPaths, len(constraints)), - TpPairToMatchNum: make(map[topologyPair]int32), + TpPairToMatchNum: make(map[topologyPair]*int32, sizeHeuristic(len(allNodes), constraints)), } - addTopologyPairMatchNum := func(pair topologyPair, num int32) { - lock.Lock() - s.TpPairToMatchNum[pair] += num - lock.Unlock() + for _, n := range allNodes { + node := n.Node() + if node == nil { + klog.Error("node not found") + continue + } + // In accordance to design, if NodeAffinity or NodeSelector is defined, + // spreading is applied to nodes that pass those filters. + if !helper.PodMatchesNodeSelectorAndAffinityTerms(pod, node) { + continue + } + // Ensure current node's labels contains all topologyKeys in 'Constraints'. + if !nodeLabelsMatchSpreadConstraints(node.Labels, constraints) { + continue + } + for _, c := range constraints { + pair := topologyPair{key: c.TopologyKey, value: node.Labels[c.TopologyKey]} + s.TpPairToMatchNum[pair] = new(int32) + } } processNode := func(i int) { nodeInfo := allNodes[i] node := nodeInfo.Node() - if node == nil { - klog.Error("node not found") - return - } - // In accordance to design, if NodeAffinity or NodeSelector is defined, - // spreading is applied to nodes that pass those filters. - if !pluginhelper.PodMatchesNodeSelectorAndAffinityTerms(pod, node) { - return - } - // Ensure current node's labels contains all topologyKeys in 'Constraints'. - if !nodeLabelsMatchSpreadConstraints(node.Labels, constraints) { - return - } for _, constraint := range constraints { - matchTotal := int32(0) - // nodeInfo.Pods() can be empty; or all pods don't fit - for _, existingPod := range nodeInfo.Pods() { - // Bypass terminating Pod (see #87621). - if existingPod.DeletionTimestamp != nil || existingPod.Namespace != pod.Namespace { - continue - } - if constraint.Selector.Matches(labels.Set(existingPod.Labels)) { - matchTotal++ - } - } pair := topologyPair{key: constraint.TopologyKey, value: node.Labels[constraint.TopologyKey]} - addTopologyPairMatchNum(pair, matchTotal) + tpCount := s.TpPairToMatchNum[pair] + if tpCount == nil { + continue + } + count := countPodsMatchSelector(nodeInfo.Pods(), constraint.Selector, pod.Namespace) + atomic.AddInt32(tpCount, int32(count)) } } parallelize.Until(context.Background(), len(allNodes), processNode) @@ -275,7 +268,7 @@ func (pl *PodTopologySpread) calPreFilterState(pod *v1.Pod) (*preFilterState, er s.TpKeyToCriticalPaths[key] = newCriticalPaths() } for pair, num := range s.TpPairToMatchNum { - s.TpKeyToCriticalPaths[pair.key].update(pair.value, num) + s.TpKeyToCriticalPaths[pair.key].update(pair.value, *num) } return &s, nil @@ -322,7 +315,10 @@ func (pl *PodTopologySpread) Filter(ctx context.Context, cycleState *framework.C // judging criteria: // 'existing matching num' + 'if self-match (1 or 0)' - 'global min matching num' <= 'maxSkew' minMatchNum := paths[0].MatchNum - matchNum := s.TpPairToMatchNum[pair] + matchNum := int32(0) + if tpCount := s.TpPairToMatchNum[pair]; tpCount != nil { + matchNum = *tpCount + } skew := matchNum + selfMatchNum - minMatchNum if skew > c.MaxSkew { klog.V(5).Infof("node '%s' failed spreadConstraint[%s]: MatchNum(%d) + selfMatchNum(%d) - minMatchNum(%d) > maxSkew(%d)", node.Name, tpKey, matchNum, selfMatchNum, minMatchNum, c.MaxSkew) @@ -332,3 +328,12 @@ func (pl *PodTopologySpread) Filter(ctx context.Context, cycleState *framework.C return nil } + +func sizeHeuristic(nodes int, constraints []topologySpreadConstraint) int { + for _, c := range constraints { + if c.TopologyKey == v1.LabelHostname { + return nodes + } + } + return 0 +} diff --git a/pkg/scheduler/framework/plugins/podtopologyspread/filtering_test.go b/pkg/scheduler/framework/plugins/podtopologyspread/filtering_test.go index 574b8e953fa..6a953ef45bb 100644 --- a/pkg/scheduler/framework/plugins/podtopologyspread/filtering_test.go +++ b/pkg/scheduler/framework/plugins/podtopologyspread/filtering_test.go @@ -30,8 +30,10 @@ import ( "k8s.io/client-go/kubernetes/fake" framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1" "k8s.io/kubernetes/pkg/scheduler/internal/cache" + "k8s.io/kubernetes/pkg/scheduler/internal/parallelize" schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" st "k8s.io/kubernetes/pkg/scheduler/testing" + "k8s.io/utils/pointer" ) var cmpOpts = []cmp.Option{ @@ -86,9 +88,9 @@ func TestPreFilterState(t *testing.T) { TpKeyToCriticalPaths: map[string]*criticalPaths{ "zone": {{"zone1", 0}, {"zone2", 0}}, }, - TpPairToMatchNum: map[topologyPair]int32{ - {key: "zone", value: "zone1"}: 0, - {key: "zone", value: "zone2"}: 0, + TpPairToMatchNum: map[topologyPair]*int32{ + {key: "zone", value: "zone1"}: pointer.Int32Ptr(0), + {key: "zone", value: "zone2"}: pointer.Int32Ptr(0), }, }, }, @@ -121,9 +123,9 @@ func TestPreFilterState(t *testing.T) { TpKeyToCriticalPaths: map[string]*criticalPaths{ "zone": {{"zone2", 2}, {"zone1", 3}}, }, - TpPairToMatchNum: map[topologyPair]int32{ - {key: "zone", value: "zone1"}: 3, - {key: "zone", value: "zone2"}: 2, + TpPairToMatchNum: map[topologyPair]*int32{ + {key: "zone", value: "zone1"}: pointer.Int32Ptr(3), + {key: "zone", value: "zone2"}: pointer.Int32Ptr(2), }, }, }, @@ -158,10 +160,10 @@ func TestPreFilterState(t *testing.T) { TpKeyToCriticalPaths: map[string]*criticalPaths{ "zone": {{"zone3", 0}, {"zone2", 2}}, }, - TpPairToMatchNum: map[topologyPair]int32{ - {key: "zone", value: "zone1"}: 3, - {key: "zone", value: "zone2"}: 2, - {key: "zone", value: "zone3"}: 0, + TpPairToMatchNum: map[topologyPair]*int32{ + {key: "zone", value: "zone1"}: pointer.Int32Ptr(3), + {key: "zone", value: "zone2"}: pointer.Int32Ptr(2), + {key: "zone", value: "zone3"}: pointer.Int32Ptr(0), }, }, }, @@ -194,9 +196,9 @@ func TestPreFilterState(t *testing.T) { TpKeyToCriticalPaths: map[string]*criticalPaths{ "zone": {{"zone2", 1}, {"zone1", 2}}, }, - TpPairToMatchNum: map[topologyPair]int32{ - {key: "zone", value: "zone1"}: 2, - {key: "zone", value: "zone2"}: 1, + TpPairToMatchNum: map[topologyPair]*int32{ + {key: "zone", value: "zone1"}: pointer.Int32Ptr(2), + {key: "zone", value: "zone2"}: pointer.Int32Ptr(1), }, }, }, @@ -238,13 +240,13 @@ func TestPreFilterState(t *testing.T) { "zone": {{"zone1", 3}, {"zone2", 4}}, "node": {{"node-x", 0}, {"node-b", 1}}, }, - TpPairToMatchNum: map[topologyPair]int32{ - {key: "zone", value: "zone1"}: 3, - {key: "zone", value: "zone2"}: 4, - {key: "node", value: "node-a"}: 2, - {key: "node", value: "node-b"}: 1, - {key: "node", value: "node-x"}: 0, - {key: "node", value: "node-y"}: 4, + TpPairToMatchNum: map[topologyPair]*int32{ + {key: "zone", value: "zone1"}: pointer.Int32Ptr(3), + {key: "zone", value: "zone2"}: pointer.Int32Ptr(4), + {key: "node", value: "node-a"}: pointer.Int32Ptr(2), + {key: "node", value: "node-b"}: pointer.Int32Ptr(1), + {key: "node", value: "node-x"}: pointer.Int32Ptr(0), + {key: "node", value: "node-y"}: pointer.Int32Ptr(4), }, }, }, @@ -287,12 +289,12 @@ func TestPreFilterState(t *testing.T) { "zone": {{"zone1", 3}, {"zone2", 4}}, "node": {{"node-b", 1}, {"node-a", 2}}, }, - TpPairToMatchNum: map[topologyPair]int32{ - {key: "zone", value: "zone1"}: 3, - {key: "zone", value: "zone2"}: 4, - {key: "node", value: "node-a"}: 2, - {key: "node", value: "node-b"}: 1, - {key: "node", value: "node-y"}: 4, + TpPairToMatchNum: map[topologyPair]*int32{ + {key: "zone", value: "zone1"}: pointer.Int32Ptr(3), + {key: "zone", value: "zone2"}: pointer.Int32Ptr(4), + {key: "node", value: "node-a"}: pointer.Int32Ptr(2), + {key: "node", value: "node-b"}: pointer.Int32Ptr(1), + {key: "node", value: "node-y"}: pointer.Int32Ptr(4), }, }, }, @@ -328,12 +330,12 @@ func TestPreFilterState(t *testing.T) { "zone": {{"zone2", 0}, {"zone1", 1}}, "node": {{"node-a", 0}, {"node-y", 0}}, }, - TpPairToMatchNum: map[topologyPair]int32{ - {key: "zone", value: "zone1"}: 1, - {key: "zone", value: "zone2"}: 0, - {key: "node", value: "node-a"}: 0, - {key: "node", value: "node-b"}: 1, - {key: "node", value: "node-y"}: 0, + TpPairToMatchNum: map[topologyPair]*int32{ + {key: "zone", value: "zone1"}: pointer.Int32Ptr(1), + {key: "zone", value: "zone2"}: pointer.Int32Ptr(0), + {key: "node", value: "node-a"}: pointer.Int32Ptr(0), + {key: "node", value: "node-b"}: pointer.Int32Ptr(1), + {key: "node", value: "node-y"}: pointer.Int32Ptr(0), }, }, }, @@ -374,12 +376,12 @@ func TestPreFilterState(t *testing.T) { "zone": {{"zone1", 3}, {"zone2", 4}}, "node": {{"node-b", 0}, {"node-a", 1}}, }, - TpPairToMatchNum: map[topologyPair]int32{ - {key: "zone", value: "zone1"}: 3, - {key: "zone", value: "zone2"}: 4, - {key: "node", value: "node-a"}: 1, - {key: "node", value: "node-b"}: 0, - {key: "node", value: "node-y"}: 2, + TpPairToMatchNum: map[topologyPair]*int32{ + {key: "zone", value: "zone1"}: pointer.Int32Ptr(3), + {key: "zone", value: "zone2"}: pointer.Int32Ptr(4), + {key: "node", value: "node-a"}: pointer.Int32Ptr(1), + {key: "node", value: "node-b"}: pointer.Int32Ptr(0), + {key: "node", value: "node-y"}: pointer.Int32Ptr(2), }, }, }, @@ -422,12 +424,12 @@ func TestPreFilterState(t *testing.T) { "zone": {{"zone1", 3}, {"zone2", 4}}, "node": {{"node-b", 1}, {"node-a", 2}}, }, - TpPairToMatchNum: map[topologyPair]int32{ - {key: "zone", value: "zone1"}: 3, - {key: "zone", value: "zone2"}: 4, - {key: "node", value: "node-a"}: 2, - {key: "node", value: "node-b"}: 1, - {key: "node", value: "node-y"}: 4, + TpPairToMatchNum: map[topologyPair]*int32{ + {key: "zone", value: "zone1"}: pointer.Int32Ptr(3), + {key: "zone", value: "zone2"}: pointer.Int32Ptr(4), + {key: "node", value: "node-a"}: pointer.Int32Ptr(2), + {key: "node", value: "node-b"}: pointer.Int32Ptr(1), + {key: "node", value: "node-y"}: pointer.Int32Ptr(4), }, }, }, @@ -459,7 +461,7 @@ func TestPreFilterState(t *testing.T) { "node": newCriticalPaths(), "rack": newCriticalPaths(), }, - TpPairToMatchNum: make(map[topologyPair]int32), + TpPairToMatchNum: make(map[topologyPair]*int32), }, }, { @@ -495,7 +497,7 @@ func TestPreFilterState(t *testing.T) { TpKeyToCriticalPaths: map[string]*criticalPaths{ "zone": newCriticalPaths(), }, - TpPairToMatchNum: make(map[topologyPair]int32), + TpPairToMatchNum: make(map[topologyPair]*int32), }, }, { @@ -572,9 +574,9 @@ func TestPreFilterStateAddPod(t *testing.T) { TpKeyToCriticalPaths: map[string]*criticalPaths{ "node": {{"node-b", 0}, {"node-a", 1}}, }, - TpPairToMatchNum: map[topologyPair]int32{ - {key: "node", value: "node-a"}: 1, - {key: "node", value: "node-b"}: 0, + TpPairToMatchNum: map[topologyPair]*int32{ + {key: "node", value: "node-a"}: pointer.Int32Ptr(1), + {key: "node", value: "node-b"}: pointer.Int32Ptr(0), }, }, }, @@ -597,9 +599,9 @@ func TestPreFilterStateAddPod(t *testing.T) { TpKeyToCriticalPaths: map[string]*criticalPaths{ "node": {{"node-a", 1}, {"node-b", 1}}, }, - TpPairToMatchNum: map[topologyPair]int32{ - {key: "node", value: "node-a"}: 1, - {key: "node", value: "node-b"}: 1, + TpPairToMatchNum: map[topologyPair]*int32{ + {key: "node", value: "node-a"}: pointer.Int32Ptr(1), + {key: "node", value: "node-b"}: pointer.Int32Ptr(1), }, }, }, @@ -622,9 +624,9 @@ func TestPreFilterStateAddPod(t *testing.T) { TpKeyToCriticalPaths: map[string]*criticalPaths{ "node": {{"node-a", 0}, {"node-b", 1}}, }, - TpPairToMatchNum: map[topologyPair]int32{ - {key: "node", value: "node-a"}: 0, - {key: "node", value: "node-b"}: 1, + TpPairToMatchNum: map[topologyPair]*int32{ + {key: "node", value: "node-a"}: pointer.Int32Ptr(0), + {key: "node", value: "node-b"}: pointer.Int32Ptr(1), }, }, }, @@ -647,9 +649,9 @@ func TestPreFilterStateAddPod(t *testing.T) { TpKeyToCriticalPaths: map[string]*criticalPaths{ "node": {{"node-a", 0}, {"node-b", 2}}, }, - TpPairToMatchNum: map[topologyPair]int32{ - {key: "node", value: "node-a"}: 0, - {key: "node", value: "node-b"}: 2, + TpPairToMatchNum: map[topologyPair]*int32{ + {key: "node", value: "node-a"}: pointer.Int32Ptr(0), + {key: "node", value: "node-b"}: pointer.Int32Ptr(2), }, }, }, @@ -672,11 +674,11 @@ func TestPreFilterStateAddPod(t *testing.T) { "zone": {{"zone2", 0}, {"zone1", 1}}, "node": {{"node-x", 0}, {"node-a", 1}}, }, - TpPairToMatchNum: map[topologyPair]int32{ - {key: "zone", value: "zone1"}: 1, - {key: "zone", value: "zone2"}: 0, - {key: "node", value: "node-a"}: 1, - {key: "node", value: "node-x"}: 0, + TpPairToMatchNum: map[topologyPair]*int32{ + {key: "zone", value: "zone1"}: pointer.Int32Ptr(1), + {key: "zone", value: "zone2"}: pointer.Int32Ptr(0), + {key: "node", value: "node-a"}: pointer.Int32Ptr(1), + {key: "node", value: "node-x"}: pointer.Int32Ptr(0), }, }, }, @@ -701,11 +703,11 @@ func TestPreFilterStateAddPod(t *testing.T) { "zone": {{"zone1", 1}, {"zone2", 1}}, "node": {{"node-a", 1}, {"node-x", 1}}, }, - TpPairToMatchNum: map[topologyPair]int32{ - {key: "zone", value: "zone1"}: 1, - {key: "zone", value: "zone2"}: 1, - {key: "node", value: "node-a"}: 1, - {key: "node", value: "node-x"}: 1, + TpPairToMatchNum: map[topologyPair]*int32{ + {key: "zone", value: "zone1"}: pointer.Int32Ptr(1), + {key: "zone", value: "zone2"}: pointer.Int32Ptr(1), + {key: "node", value: "node-a"}: pointer.Int32Ptr(1), + {key: "node", value: "node-x"}: pointer.Int32Ptr(1), }, }, }, @@ -733,12 +735,12 @@ func TestPreFilterStateAddPod(t *testing.T) { "zone": {{"zone2", 1}, {"zone1", 3}}, "node": {{"node-a", 1}, {"node-x", 1}}, }, - TpPairToMatchNum: map[topologyPair]int32{ - {key: "zone", value: "zone1"}: 3, - {key: "zone", value: "zone2"}: 1, - {key: "node", value: "node-a"}: 1, - {key: "node", value: "node-b"}: 2, - {key: "node", value: "node-x"}: 1, + TpPairToMatchNum: map[topologyPair]*int32{ + {key: "zone", value: "zone1"}: pointer.Int32Ptr(3), + {key: "zone", value: "zone2"}: pointer.Int32Ptr(1), + {key: "node", value: "node-a"}: pointer.Int32Ptr(1), + {key: "node", value: "node-b"}: pointer.Int32Ptr(2), + {key: "node", value: "node-x"}: pointer.Int32Ptr(1), }, }, }, @@ -773,12 +775,12 @@ func TestPreFilterStateAddPod(t *testing.T) { "zone": {{"zone2", 1}, {"zone1", 2}}, "node": {{"node-a", 0}, {"node-b", 1}}, }, - TpPairToMatchNum: map[topologyPair]int32{ - {key: "zone", value: "zone1"}: 2, - {key: "zone", value: "zone2"}: 1, - {key: "node", value: "node-a"}: 0, - {key: "node", value: "node-b"}: 1, - {key: "node", value: "node-x"}: 2, + TpPairToMatchNum: map[topologyPair]*int32{ + {key: "zone", value: "zone1"}: pointer.Int32Ptr(2), + {key: "zone", value: "zone2"}: pointer.Int32Ptr(1), + {key: "node", value: "node-a"}: pointer.Int32Ptr(0), + {key: "node", value: "node-b"}: pointer.Int32Ptr(1), + {key: "node", value: "node-x"}: pointer.Int32Ptr(2), }, }, }, @@ -813,12 +815,12 @@ func TestPreFilterStateAddPod(t *testing.T) { "zone": {{"zone1", 1}, {"zone2", 1}}, "node": {{"node-a", 1}, {"node-b", 1}}, }, - TpPairToMatchNum: map[topologyPair]int32{ - {key: "zone", value: "zone1"}: 1, - {key: "zone", value: "zone2"}: 1, - {key: "node", value: "node-a"}: 1, - {key: "node", value: "node-b"}: 1, - {key: "node", value: "node-x"}: 2, + TpPairToMatchNum: map[topologyPair]*int32{ + {key: "zone", value: "zone1"}: pointer.Int32Ptr(1), + {key: "zone", value: "zone2"}: pointer.Int32Ptr(1), + {key: "node", value: "node-a"}: pointer.Int32Ptr(1), + {key: "node", value: "node-b"}: pointer.Int32Ptr(1), + {key: "node", value: "node-x"}: pointer.Int32Ptr(2), }, }, }, @@ -894,9 +896,9 @@ func TestPreFilterStateRemovePod(t *testing.T) { TpKeyToCriticalPaths: map[string]*criticalPaths{ "zone": {{"zone1", 1}, {"zone2", 1}}, }, - TpPairToMatchNum: map[topologyPair]int32{ - {key: "zone", value: "zone1"}: 1, - {key: "zone", value: "zone2"}: 1, + TpPairToMatchNum: map[topologyPair]*int32{ + {key: "zone", value: "zone1"}: pointer.Int32Ptr(1), + {key: "zone", value: "zone2"}: pointer.Int32Ptr(1), }, }, }, @@ -924,9 +926,9 @@ func TestPreFilterStateRemovePod(t *testing.T) { TpKeyToCriticalPaths: map[string]*criticalPaths{ "zone": {{"zone1", 1}, {"zone2", 2}}, }, - TpPairToMatchNum: map[topologyPair]int32{ - {key: "zone", value: "zone1"}: 1, - {key: "zone", value: "zone2"}: 2, + TpPairToMatchNum: map[topologyPair]*int32{ + {key: "zone", value: "zone1"}: pointer.Int32Ptr(1), + {key: "zone", value: "zone2"}: pointer.Int32Ptr(2), }, }, }, @@ -955,9 +957,9 @@ func TestPreFilterStateRemovePod(t *testing.T) { TpKeyToCriticalPaths: map[string]*criticalPaths{ "zone": {{"zone1", 2}, {"zone2", 2}}, }, - TpPairToMatchNum: map[topologyPair]int32{ - {key: "zone", value: "zone1"}: 2, - {key: "zone", value: "zone2"}: 2, + TpPairToMatchNum: map[topologyPair]*int32{ + {key: "zone", value: "zone1"}: pointer.Int32Ptr(2), + {key: "zone", value: "zone2"}: pointer.Int32Ptr(2), }, }, }, @@ -986,9 +988,9 @@ func TestPreFilterStateRemovePod(t *testing.T) { TpKeyToCriticalPaths: map[string]*criticalPaths{ "zone": {{"zone1", 2}, {"zone2", 2}}, }, - TpPairToMatchNum: map[topologyPair]int32{ - {key: "zone", value: "zone1"}: 2, - {key: "zone", value: "zone2"}: 2, + TpPairToMatchNum: map[topologyPair]*int32{ + {key: "zone", value: "zone1"}: pointer.Int32Ptr(2), + {key: "zone", value: "zone2"}: pointer.Int32Ptr(2), }, }, }, @@ -1018,12 +1020,12 @@ func TestPreFilterStateRemovePod(t *testing.T) { "zone": {{"zone2", 1}, {"zone1", 3}}, "node": {{"node-b", 1}, {"node-x", 1}}, }, - TpPairToMatchNum: map[topologyPair]int32{ - {key: "zone", value: "zone1"}: 3, - {key: "zone", value: "zone2"}: 1, - {key: "node", value: "node-a"}: 2, - {key: "node", value: "node-b"}: 1, - {key: "node", value: "node-x"}: 1, + TpPairToMatchNum: map[topologyPair]*int32{ + {key: "zone", value: "zone1"}: pointer.Int32Ptr(3), + {key: "zone", value: "zone2"}: pointer.Int32Ptr(1), + {key: "node", value: "node-a"}: pointer.Int32Ptr(2), + {key: "node", value: "node-b"}: pointer.Int32Ptr(1), + {key: "node", value: "node-x"}: pointer.Int32Ptr(1), }, }, }, @@ -1065,7 +1067,7 @@ func TestPreFilterStateRemovePod(t *testing.T) { } } -func BenchmarkTestCalPreFilterState(b *testing.B) { +func BenchmarkFilter(b *testing.B) { tests := []struct { name string pod *v1.Pod @@ -1103,17 +1105,30 @@ func BenchmarkTestCalPreFilterState(b *testing.B) { }, } for _, tt := range tests { + var state *framework.CycleState b.Run(tt.name, func(b *testing.B) { existingPods, allNodes, _ := st.MakeNodesAndPodsForEvenPodsSpread(tt.pod.Labels, tt.existingPodsNum, tt.allNodesNum, tt.filteredNodesNum) pl := PodTopologySpread{ sharedLister: cache.NewSnapshot(existingPods, allNodes), } + ctx := context.Background() b.ResetTimer() for i := 0; i < b.N; i++ { - s := pl.PreFilter(context.Background(), framework.NewCycleState(), tt.pod) + state = framework.NewCycleState() + s := pl.PreFilter(ctx, state, tt.pod) if !s.IsSuccess() { b.Fatal(s.AsError()) } + filterNode := func(i int) { + n, _ := pl.sharedLister.NodeInfos().Get(allNodes[i].Name) + pl.Filter(ctx, state, tt.pod, n) + } + parallelize.Until(ctx, len(allNodes), filterNode) + } + }) + b.Run(tt.name+"/Clone", func(b *testing.B) { + for i := 0; i < b.N; i++ { + state.Clone() } }) }