Skip to content

Commit

Permalink
feat: Added RangeNoOrdered function to quickly traverse the elements …
Browse files Browse the repository at this point in the history
…in the Splay tree without worrying about the order. And updated the result of GetPods to be unordered.
  • Loading branch information
slipegg committed Oct 17, 2024
1 parent e25741f commit faed7e3
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 123 deletions.
2 changes: 1 addition & 1 deletion pkg/framework/api/nodeinfo_podinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ func (m *PodInfoMaintainer) Len() int {
func (m *PodInfoMaintainer) GetPods() []*PodInfo {
pods := make([]*PodInfo, 0, m.bePodsMayBePreempted.Len()+m.gtPodsMayBePreempted.Len()+len(m.neverBePreempted))
rangeSplay := func(s splay.Splay) {
s.Range(func(so splay.StoredObj) {
s.RangeNoOrder(func(so splay.StoredObj) {
pods = append(pods, so.(*PodInfo))
})
}
Expand Down
122 changes: 0 additions & 122 deletions pkg/framework/api/nodeinfo_podinfo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,7 @@ import (
"math"
"reflect"
"testing"
"time"

"github.com/google/go-cmp/cmp"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand All @@ -36,126 +34,6 @@ func makePriority(priority int32) *int32 {
return &priority
}

func TestPodInfoMaintainer_GetPods(t *testing.T) {
t0 := time.Now()
t1 := t0.Add(time.Hour)

p0 := NewPodInfo(&v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "p0",
UID: "p0",
Annotations: map[string]string{
podutil.PodResourceTypeAnnotationKey: string(podutil.GuaranteedPod),
},
},
Spec: v1.PodSpec{
Priority: makePriority(0),
NodeName: "node",
},
Status: v1.PodStatus{
StartTime: &metav1.Time{t1},
},
})
// p1 should be more important than p0 cause `Priority`.
p1 := NewPodInfo(&v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "p1",
UID: "p1",
Annotations: map[string]string{
podutil.PodResourceTypeAnnotationKey: string(podutil.GuaranteedPod),
},
},
Spec: v1.PodSpec{
Priority: makePriority(5),
NodeName: "node",
},
Status: v1.PodStatus{
StartTime: &metav1.Time{t1},
},
})
// p2 should be more important than p1 cause `StartTime`.
p2 := NewPodInfo(&v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "p2",
UID: "p2",
Annotations: map[string]string{
podutil.PodResourceTypeAnnotationKey: string(podutil.GuaranteedPod),
},
},
Spec: v1.PodSpec{
Priority: makePriority(5),
NodeName: "node",
},
Status: v1.PodStatus{
StartTime: &metav1.Time{t0},
},
})
// p3 should be more important than p8 cause `StartTime`.
p3 := NewPodInfo(&v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "p3",
UID: "p3",
Annotations: map[string]string{
podutil.PodResourceTypeAnnotationKey: string(podutil.GuaranteedPod),
},
},
Spec: v1.PodSpec{
Priority: makePriority(5),
NodeName: "node",
},
Status: v1.PodStatus{
StartTime: &metav1.Time{t0},
},
})
// p4 should be more important than p3 cause `PodKey`.
p4 := NewPodInfo(&v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "pa",
UID: "pa",
Annotations: map[string]string{
podutil.PodResourceTypeAnnotationKey: string(podutil.GuaranteedPod),
},
},
Spec: v1.PodSpec{
Priority: makePriority(5),
NodeName: "node",
},
Status: v1.PodStatus{
StartTime: &metav1.Time{t0},
},
})

tests := []struct {
name string
pods []*PodInfo
want []*PodInfo
}{
{
name: "test",
pods: []*PodInfo{p4, p2, p0, p3, p1},
want: []*PodInfo{p0, p1, p2, p3, p4},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
for i := 0; i < len(tt.want); i++ {
for j := 0; j < i; j++ {
if !tt.want[i].Compare(tt.want[j]) {
t.Errorf("PodInfo.Compare got false for pod: %v, %v", tt.want[i].PodKey, tt.want[j].PodKey)
}
}
}

m := NewPodInfoMaintainer(tt.pods...)

t.Logf(m.gtPodsMayBePreempted.PrintTree())
if diff := cmp.Diff(m.GetPods(), tt.want); diff != "" {
t.Errorf("PodInfoMaintainer.GetPods() diff = %v", diff)
}
})
}
}

func TestGetMaintainableInfoByPartition(t *testing.T) {
makePod := func(name string, priority int32, req v1.ResourceList) *v1.Pod {
return &v1.Pod{
Expand Down
10 changes: 10 additions & 0 deletions pkg/util/splay/splay.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ type Splay interface {
Clone() Splay
// PrintTree outputs splay in the form of a tree diagram.
PrintTree() string
// Range traverses the entire splay quickly. Note that the order of traversal is not guaranteed
RangeNoOrder(RangeFunc)
}

type splay struct {
Expand Down Expand Up @@ -387,6 +389,14 @@ func (s *splay) PrintTree() string {
return output.String()
}

func (s *splay) RangeNoOrder(f RangeFunc) {
for i, node := range s.items {
if i != s.minv && i != s.maxv && i != 0 {
f(node.obj)
}
}
}

// getChildIndex indicates whether `x` is the right child of `y`.
func (s *splay) getChildIndex(x, y int) int {
if y != 0 && s.items[y].rchild == x {
Expand Down
38 changes: 38 additions & 0 deletions pkg/util/splay/splay_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,44 @@ func Test_Splay(t *testing.T) {
t.Logf("After j=%v got splay: %s\n", j, s)
}
}
func Test_Splay_No_Order_Range(t *testing.T) {
s := NewSplay()

for i := 1; i < 100; i++ {
s.Insert(makeObj(i, i))
}

var noOrderObjs []StoredObj
s.RangeNoOrder(func(so StoredObj) {
noOrderObjs = append(noOrderObjs, so)
})

var orderObjs []StoredObj
s.Range(func(so StoredObj) {
orderObjs = append(orderObjs, so)
})

if len(noOrderObjs) != len(orderObjs) {
t.Errorf("Length mismatch: List has %d items, Range has %d items", len(noOrderObjs), len(orderObjs))
}

// Tests if elements are identical (order doesn't matter)
counts := make(map[StoredObj]int)

for _, obj := range noOrderObjs {
counts[obj]++
}
for _, obj := range orderObjs {
counts[obj]--
}

for _, count := range counts {
if count != 0 {
t.Error("Mismatch between onOrderedObjs and rangeObjs elements")
return
}
}
}

func Test_Rotate(t *testing.T) {
s := NewSplay()
Expand Down

0 comments on commit faed7e3

Please sign in to comment.