Skip to content

Commit b92d0e6

Browse files
nirrozenbaumvMaroon
authored andcommitted
add max score picker (kubernetes-sigs#752)
* embedded Pod interface into ScoredPod struct. updated tests and picker accordingly Signed-off-by: Nir Rozenbaum <[email protected]> * implemented max-score picker Signed-off-by: Maroon Ayoub <[email protected]> * minor changes in max score picker Signed-off-by: Nir Rozenbaum <[email protected]> --------- Signed-off-by: Nir Rozenbaum <[email protected]> Signed-off-by: Maroon Ayoub <[email protected]> Co-authored-by: Maroon Ayoub <[email protected]>
1 parent 65168db commit b92d0e6

File tree

4 files changed

+78
-25
lines changed

4 files changed

+78
-25
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package picker
2+
3+
import (
4+
"fmt"
5+
6+
"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/scheduling/plugins"
7+
"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/scheduling/types"
8+
logutil "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/util/logging"
9+
)
10+
11+
var _ plugins.Picker = &MaxScorePicker{}
12+
13+
func NewMaxScorePicker() plugins.Picker {
14+
return &MaxScorePicker{
15+
random: &RandomPicker{},
16+
}
17+
}
18+
19+
// MaxScorePicker picks the pod with the maximum score from the list of candidates.
20+
type MaxScorePicker struct {
21+
random *RandomPicker
22+
}
23+
24+
// Name returns the name of the picker.
25+
func (p *MaxScorePicker) Name() string {
26+
return "max_score"
27+
}
28+
29+
// Pick selects the pod with the maximum score from the list of candidates.
30+
func (p *MaxScorePicker) Pick(ctx *types.SchedulingContext, scoredPods []*types.ScoredPod) *types.Result {
31+
ctx.Logger.V(logutil.DEBUG).Info(fmt.Sprintf("Selecting a pod with the max score from %d candidates: %+v", len(scoredPods), scoredPods))
32+
33+
highestScorePods := []*types.ScoredPod{}
34+
maxScore := -1.0 // pods min score is 0, putting value lower than 0 in order to find at least one pod as highest
35+
for _, pod := range scoredPods {
36+
if pod.Score > maxScore {
37+
maxScore = pod.Score
38+
highestScorePods = []*types.ScoredPod{pod}
39+
} else if pod.Score == maxScore {
40+
highestScorePods = append(highestScorePods, pod)
41+
}
42+
}
43+
44+
if len(highestScorePods) > 1 {
45+
return p.random.Pick(ctx, highestScorePods) // pick randomly from the highest score pods
46+
}
47+
48+
return &types.Result{TargetPod: highestScorePods[0]}
49+
}

pkg/epp/scheduling/plugins/picker/random_picker.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@ var _ plugins.Picker = &RandomPicker{}
3030
// RandomPicker picks a random pod from the list of candidates.
3131
type RandomPicker struct{}
3232

33-
func (rp *RandomPicker) Name() string {
33+
func (p *RandomPicker) Name() string {
3434
return "random"
3535
}
3636

37-
func (rp *RandomPicker) Pick(ctx *types.SchedulingContext, scoredPods []*types.ScoredPod) *types.Result {
37+
func (p *RandomPicker) Pick(ctx *types.SchedulingContext, scoredPods []*types.ScoredPod) *types.Result {
3838
ctx.Logger.V(logutil.DEBUG).Info(fmt.Sprintf("Selecting a random pod from %d candidates: %+v", len(scoredPods), scoredPods))
3939
i := rand.Intn(len(scoredPods))
40-
return &types.Result{TargetPod: scoredPods[i].Pod}
40+
return &types.Result{TargetPod: scoredPods[i]}
4141
}

pkg/epp/scheduling/scheduler_test.go

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -93,17 +93,19 @@ func TestSchedule(t *testing.T) {
9393
},
9494
},
9595
wantRes: &types.Result{
96-
TargetPod: &types.PodMetrics{
97-
Pod: &backendmetrics.Pod{NamespacedName: k8stypes.NamespacedName{Name: "pod2"}},
98-
Metrics: &backendmetrics.Metrics{
99-
WaitingQueueSize: 3,
100-
KVCacheUsagePercent: 0.1,
101-
MaxActiveModels: 2,
102-
ActiveModels: map[string]int{
103-
"foo": 1,
104-
"critical": 1,
96+
TargetPod: &types.ScoredPod{
97+
Pod: &types.PodMetrics{
98+
Pod: &backendmetrics.Pod{NamespacedName: k8stypes.NamespacedName{Name: "pod2"}},
99+
Metrics: &backendmetrics.Metrics{
100+
WaitingQueueSize: 3,
101+
KVCacheUsagePercent: 0.1,
102+
MaxActiveModels: 2,
103+
ActiveModels: map[string]int{
104+
"foo": 1,
105+
"critical": 1,
106+
},
107+
WaitingModels: map[string]int{},
105108
},
106-
WaitingModels: map[string]int{},
107109
},
108110
},
109111
},
@@ -154,17 +156,19 @@ func TestSchedule(t *testing.T) {
154156
},
155157
},
156158
wantRes: &types.Result{
157-
TargetPod: &types.PodMetrics{
158-
Pod: &backendmetrics.Pod{NamespacedName: k8stypes.NamespacedName{Name: "pod1"}},
159-
Metrics: &backendmetrics.Metrics{
160-
WaitingQueueSize: 0,
161-
KVCacheUsagePercent: 0.2,
162-
MaxActiveModels: 2,
163-
ActiveModels: map[string]int{
164-
"foo": 1,
165-
"bar": 1,
159+
TargetPod: &types.ScoredPod{
160+
Pod: &types.PodMetrics{
161+
Pod: &backendmetrics.Pod{NamespacedName: k8stypes.NamespacedName{Name: "pod1"}},
162+
Metrics: &backendmetrics.Metrics{
163+
WaitingQueueSize: 0,
164+
KVCacheUsagePercent: 0.2,
165+
MaxActiveModels: 2,
166+
ActiveModels: map[string]int{
167+
"foo": 1,
168+
"bar": 1,
169+
},
170+
WaitingModels: map[string]int{},
166171
},
167-
WaitingModels: map[string]int{},
168172
},
169173
},
170174
},
@@ -505,7 +509,7 @@ func findPods(ctx *types.SchedulingContext, names ...k8stypes.NamespacedName) []
505509
func getPodScore(scoredPods []*types.ScoredPod, selectedPod types.Pod) float64 {
506510
finalScore := 0.0
507511
for _, scoredPod := range scoredPods {
508-
if scoredPod.Pod.GetPod().NamespacedName.String() == selectedPod.GetPod().NamespacedName.String() {
512+
if scoredPod.GetPod().NamespacedName.String() == selectedPod.GetPod().NamespacedName.String() {
509513
finalScore = scoredPod.Score
510514
break
511515
}

pkg/epp/scheduling/types/types.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ type Pod interface {
4747
}
4848

4949
type ScoredPod struct {
50-
Pod Pod
50+
Pod
5151
Score float64
5252
}
5353

0 commit comments

Comments
 (0)