-
Notifications
You must be signed in to change notification settings - Fork 385
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Sort pods to be executed by multi dimensions; Sort func orders can be…
… customized
- Loading branch information
kaiyuechen
committed
Mar 13, 2022
1 parent
2a39201
commit d42e963
Showing
13 changed files
with
578 additions
and
172 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,182 @@ | ||
package sort | ||
|
||
import ( | ||
"sort" | ||
|
||
v1 "k8s.io/api/core/v1" | ||
|
||
"github.com/gocrane/crane/pkg/ensurance/executor" | ||
"github.com/gocrane/crane/pkg/utils" | ||
) | ||
|
||
// EvictRankFunc sorts the pods in eviction order | ||
type EvictRankFunc func(pods []executor.EvictPod) | ||
|
||
var evictSortFunc = map[string]func(p1, p2 executor.EvictPod) int{ | ||
"ExtResourceEnable": evictUseExtResource, | ||
"ClassAndPriority": evictClassAndPriority, | ||
"ExtResourceUsage": evictExtCpuUsed2Limit, | ||
"CpuUsage": evictCpuUsage, | ||
"RunningTime": evictStartTime, | ||
} | ||
|
||
func EvictRankFuncConstruct(customize []string) EvictRankFunc { | ||
var evictRankFunc EvictRankFunc | ||
if len(customize) == 0 { | ||
cmp := []cmpEvictFunc{} | ||
for _, sortFunc := range customize { | ||
if f, ok := evictSortFunc[sortFunc]; ok { | ||
cmp = append(cmp,f) | ||
} | ||
evictRankFunc = evictOrderedBy(cmp...).Sort | ||
return evictRankFunc | ||
} | ||
} | ||
evictRankFunc = evictRankCpuPressure | ||
|
||
return evictRankFunc | ||
} | ||
|
||
func evictRankCpuPressure(pods []executor.EvictPod) { | ||
evictOrderedBy(evictUseExtResource, evictClassAndPriority, evictExtCpuUsed2Limit, evictCpuUsage, evictStartTime).Sort(pods) | ||
} | ||
|
||
// evictStartTime compares pods by pod's start time | ||
func evictStartTime(p1, p2 executor.EvictPod) int { | ||
t1 := p1.StartTime | ||
t2 := p2.StartTime | ||
|
||
if t1 == nil && t2 == nil { | ||
return 0 | ||
} | ||
if t1 == nil { | ||
// maybe t1 is just starting | ||
return 1 | ||
} | ||
if t2 == nil { | ||
return -1 | ||
} | ||
|
||
if t1.Before(t2) { | ||
return 1 | ||
} else if t1.Equal(t2) { | ||
return 0 | ||
} | ||
return -1 | ||
} | ||
|
||
// evictClassAndPriority compares pods by pod's ClassAndPriority | ||
func evictClassAndPriority(p1, p2 executor.EvictPod) int { | ||
return int(executor.CompareClassAndPriority(p1.ClassAndPriority, p2.ClassAndPriority)) | ||
} | ||
|
||
// evictUseExtResource compares pod by whether use ext resource | ||
func evictUseExtResource(p1, p2 executor.EvictPod) int { | ||
use1 := utils.TransBool2Uint(p1.UseExtResource) | ||
use2 := utils.TransBool2Uint(p2.UseExtResource) | ||
|
||
if use1 == use2 { | ||
return 0 | ||
} | ||
if use1 < use2 { | ||
return -1 | ||
} | ||
return 1 | ||
} | ||
|
||
// evictExtCpuUsed2Limit compares the partition extcpu usage of extcpu limit | ||
func evictExtCpuUsed2Limit(p1, p2 executor.EvictPod) int { | ||
// if both pod don't use ext resource, then return | ||
if p1.UseExtResource == false && p2.UseExtResource == false { | ||
return 0 | ||
} | ||
|
||
p1Ratio := p1.PodCPUUsage / float64(p1.ExtCpuLimit) | ||
p2Ratio := p2.PodCPUUsage / float64(p2.ExtCpuLimit) | ||
|
||
if utils.AlmostEqual(p1Ratio, p2Ratio) { | ||
return 0 | ||
} | ||
if p1Ratio < p2Ratio { | ||
return -1 | ||
} | ||
return 1 | ||
} | ||
|
||
// evictCpuUsage compares the partition extcpu usage of extcpu limit | ||
func evictCpuUsage(p1, p2 executor.EvictPod) int { | ||
var p1usage, p2usage float64 | ||
// if both pod is PodQOSBestEffort, then compare the absolute usage;otherwise, cmpare the ratio compared with PodCPUQuota | ||
if p1.ClassAndPriority.PodQOSClass == v1.PodQOSBestEffort && p2.ClassAndPriority.PodQOSClass == v1.PodQOSBestEffort { | ||
p1usage = p1.PodCPUUsage | ||
p2usage = p2.PodCPUUsage | ||
} else { | ||
p1usage = p1.PodCPUUsage * p1.PodCPUPeriod / p1.PodCPUQuota | ||
p2usage = p2.PodCPUUsage * p2.PodCPUPeriod / p2.PodCPUQuota | ||
} | ||
if utils.AlmostEqual(p1usage, p2usage) { | ||
return 0 | ||
} | ||
if p1usage < p2usage { | ||
return -1 | ||
} | ||
return 1 | ||
} | ||
|
||
// Cmp compares p1 and p2 and returns: | ||
// | ||
// -1 if p1 < p2 | ||
// 0 if p1 == p2 | ||
// +1 if p1 > p2 | ||
// | ||
type cmpEvictFunc func(p1, p2 executor.EvictPod) int | ||
|
||
// evictSorter implements the Sort interface, sorting changes within. | ||
type evictSorter struct { | ||
pods []executor.EvictPod | ||
cmp []cmpEvictFunc | ||
} | ||
|
||
// Sort sorts the argument slice according to the less functions passed to evictOrderedBy. | ||
func (ms *evictSorter) Sort(pods []executor.EvictPod) { | ||
ms.pods = pods | ||
sort.Sort(ms) | ||
} | ||
|
||
// evictOrderedBy returns a Sorter that sorts using the cmp functions, in order. | ||
// Call its Sort method to sort the data. | ||
func evictOrderedBy(cmp ...cmpEvictFunc) *evictSorter { | ||
return &evictSorter{ | ||
cmp: cmp, | ||
} | ||
} | ||
|
||
// Len is part of sort.Interface. | ||
func (ms *evictSorter) Len() int { | ||
return len(ms.pods) | ||
} | ||
|
||
// Swap is part of sort.Interface. | ||
func (ms *evictSorter) Swap(i, j int) { | ||
ms.pods[i], ms.pods[j] = ms.pods[j], ms.pods[i] | ||
} | ||
|
||
// Less is part of sort.Interface. | ||
func (ms *evictSorter) Less(i, j int) bool { | ||
p1, p2 := ms.pods[i], ms.pods[j] | ||
var k int | ||
for k = 0; k < len(ms.cmp)-1; k++ { | ||
cmpResult := ms.cmp[k](p1, p2) | ||
// p1 is less than p2 | ||
if cmpResult < 0 { | ||
return true | ||
} | ||
// p1 is greater than p2 | ||
if cmpResult > 0 { | ||
return false | ||
} | ||
// we don't know yet | ||
} | ||
// the last cmp func is the final decider | ||
return ms.cmp[k](p1, p2) < 0 | ||
} |
Oops, something went wrong.