Merge pull request #89665 from alculquicondor/per_node_filter_spreading

Optimize topology spreading filter
This commit is contained in:
Kubernetes Prow Robot 2020-03-31 16:43:41 -07:00 committed by GitHub
commit dda530cfb7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 169 additions and 149 deletions

View File

@ -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] = &copyCount
}
return &copy
}
@ -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)),
}
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)
}
addTopologyPairMatchNum := func(pair topologyPair, num int32) {
lock.Lock()
s.TpPairToMatchNum[pair] += num
lock.Unlock()
}
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 {
pair := topologyPair{key: constraint.TopologyKey, value: node.Labels[constraint.TopologyKey]}
tpCount := s.TpPairToMatchNum[pair]
if tpCount == nil {
continue
}
if constraint.Selector.Matches(labels.Set(existingPod.Labels)) {
matchTotal++
}
}
pair := topologyPair{key: constraint.TopologyKey, value: node.Labels[constraint.TopologyKey]}
addTopologyPairMatchNum(pair, matchTotal)
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
}

View File

@ -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()
}
})
}