You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@yunikorn.apache.org by "weichen lai (Jira)" <ji...@apache.org> on 2026/09/06 13:23:00 UTC

[jira] [Created] (YUNIKORN-3445) [Core] SortAllocationsBasedOnAsk prioritizes originator and opted-out pods for preemption instead of protecting them

weichen lai created YUNIKORN-3445:
-------------------------------------

             Summary: [Core] SortAllocationsBasedOnAsk prioritizes originator and opted-out pods for preemption instead of protecting them
                 Key: YUNIKORN-3445
                 URL: https://issues.apache.org/jira/browse/YUNIKORN-3445
             Project: Apache YuniKorn
          Issue Type: Bug
          Components: core - scheduler
    Affects Versions: 1.9.0
            Reporter: weichen lai
            Assignee: weichen lai


h3. Overview

In {{pkg/scheduler/objects/preemption_utilities.go}}, {{SortAllocationsBasedOnAsk()}} and {{scoreAllocationBasedOnAsk()}} determine victim ordering during preemption.

Under the current implementation, allocations with {{!allowPreemptSelf}} (opted-out) or {{isOriginator}} (driver/manager) receive higher-order score bits ({{scoreNoPreempt}} = {{1 << 34}}, {{scoreOriginator}} = {{1 << 33}}):

{code:go}func scoreAllocationBasedOnAsk(allocation *Allocation, ask *resources.Resource) uint64 {
	var score uint64 = 0
	if allocation.IsOriginator() {
		score |= scoreOriginator // 1 << 33
	}
	if !allocation.IsAllowPreemptSelf() {
		score |= scoreNoPreempt  // 1 << 34
	}
	score += allocation.GetAllocatedResource().TypeMatching(ask)
	return score
}
{code}

Because {{SortAllocationsBasedOnAsk()}} orders allocations in descending order ({{scoreLeft > scoreRight}}), opted-out and originator allocations receive higher scores and are placed at the beginning of the candidate slice rather than at the end.
h2. 

h3. Comparison with Design Documentation

This ordering conflicts with documented design specifications:
* **Preemption Law #1 (preemption policies are strong suggestions, not guarantees):** Opting out of preemption and originator status are intended as a last resort when no other suitable allocations can be preempted.
* **Quota Preemption Design Document:** The specification states that non-originators and pods with {{allowPreemption: true}} should receive higher scores to prioritize regular allocations for preemption over originators and opted-out pods.
h2. 

h3. Test Verification

The following test demonstrates the ordering in {{pkg/scheduler/objects/preemption_utilities_test.go}}:

{code:go}func TestSortAllocationsBasedOnAsk_PreemptionOrdering(t *testing.T) {
	node := NewNode(&si.NodeInfo{
		NodeID: "node1",
		SchedulableResource: &si.Resource{
			Resources: map[string]*si.Quantity{"first": {Value: 100}},
		},
	})
	res := resources.NewResourceFromMap(map[string]resources.Quantity{"first": 10})
	total := resources.NewResourceFromMap(map[string]resources.Quantity{"first": 100})
	ask := resources.NewResourceFromMap(map[string]resources.Quantity{"first": 10})

	regularPod := createAllocation("regularPod", "app1", node.NodeID, true, false, 10, false, res)
	originatorPod := createAllocation("originatorPod", "app1", node.NodeID, true, true, 10, false, res)
	optedOutPod := createAllocation("optedOutPod", "app1", node.NodeID, false, false, 10, false, res)

	allocations := []*Allocation{regularPod, originatorPod, optedOutPod}
	SortAllocationsBasedOnAsk(allocations, total, ask)

	// Current ordering:
	// allocations[0]: optedOutPod
	// allocations[1]: originatorPod
	// allocations[2]: regularPod
	//
	// Expected ordering per design: regularPod should be placed at index 0
	assert.Equal(t, allocations[0].GetAllocationKey(), "regularPod",
		"Expected regularPod at index 0, but got: %s", allocations[0].GetAllocationKey())
}
{code}

*Output:*
{code}=== RUN   TestSortAllocationsBasedOnAsk_PreemptionOrdering
    preemption_utilities_test.go:320: Expected regularPod at index 0, but got: optedOutPod
--- FAIL: TestSortAllocationsBasedOnAsk_PreemptionOrdering (0.00s)
{code}
h2. 

h3. Impact

During Quota Preemption, reducing a queue's quota results in originator and opted-out allocations being preempted before standard worker allocations.
h2. 

h3. Proposed Solution

In {{pkg/scheduler/objects/preemption_utilities.go}}, assign the higher-order score bits to unprotected allocations ({{allowPreemptSelf == true}} and {{!isOriginator}}):

{code:go}const (
	scoreAllowPreempt  uint64 = 1 << 34
	scoreNonOriginator uint64 = 1 << 33
)

func scoreAllocationBasedOnAsk(allocation *Allocation, ask *resources.Resource) uint64 {
	var score uint64 = 0
	if !allocation.IsOriginator() {
		score |= scoreNonOriginator
	}
	if allocation.IsAllowPreemptSelf() {
		score |= scoreAllowPreempt
	}
	score += allocation.GetAllocatedResource().TypeMatching(ask)
	return score
}
{code}



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@yunikorn.apache.org
For additional commands, e-mail: dev-help@yunikorn.apache.org