Skip to content

feat(scheduler): evict for deferred in-place resizes behind opt-in action - #2051

Draft
gshaibi wants to merge 36 commits into
mainfrom
feat/deferred-resize-eviction
Draft

feat(scheduler): evict for deferred in-place resizes behind opt-in action#2051
gshaibi wants to merge 36 commits into
mainfrom
feat/deferred-resize-eviction

Conversation

@gshaibi

@gshaibi gshaibi commented Aug 10, 2026

Copy link
Copy Markdown
Member

Description

Implements deferred resize eviction — goal 3 of the in-place pod resize design, left out of scope there.

When the kubelet marks an in-place resize Deferred (PodResizePending condition) because the node lacks capacity, KAI currently frees nothing, so the resize can starve indefinitely even when the node runs workloads a new pod of that size would be allowed to displace.

This PR adds a new scheduler action, resizeeviction, disabled by default, that evicts victims on the resizing pod's node until the kubelet can enact the resize:

  • Detection: pods with PodResizePending/Deferred for the current resize generation; the still-unallocated delta is spec − actual per resizable resource (CPU/memory).
  • Demand model: the effective-request accounting from feat(scheduler,admission): implement in-place pod resize accounting and queue admission #2021 already charges a deferred resize at max(spec, actual) on both node and queue, so the demand is a node-local scalar shortfall (Used − Releasing − other deferred deltas − Allocatable), and the freed capacity stays reserved across cycles — that is also the thrash guard. No virtual pending task and no scenario-solver surgery; the pod is bound, nothing needs placement.
  • Victim selection: exactly the rules a new pod of that size would face, reusing the existing session callbacks — same-queue victims under preempt rules (preemptible, lower priority, PreemptVictimFilter), cross-queue victims under reclaim rules (CanReclaimResources + ReclaimVictimFilter), ordered by the standard victims queue, gang/elastic semantics via GetTasksToEvict, and the accumulated victim set validated by PreemptScenarioValidator / ReclaimScenarioValidatorFn before commit. Eviction is all-or-nothing per resizing pod.
  • Configuration: registered but not in the default actions list. Operator users enable per shard with spec.actions.resizeeviction.enabled: true (default priority 150, after preempt); raw-config users append resizeeviction to the actions string.

Design doc: docs/developer/designs/in-place-pod-resize/deferred-resize-eviction.md (rationale, decisions, known limitations). User docs updated in docs/in-place-resize/README.md and docs/operator/scheduler-config-customization.md.

Stacked on #2021 (claude/pr-1997-implementation-2f767b): the effective-request accounting and the pod-transform retention of resize fields are prerequisites. Until #2021 merges, this diff includes its commits; only the four commits from feat(scheduler): add resizeeviction action… onward are new here.

Related Issues

Fixes #1872

Checklist

  • Self-reviewed
  • Added/updated tests (if needed)
  • Updated documentation (if needed)
  • Added a changelog fragment via make changelog (or applied the skip-changelog label). Do not edit CHANGELOG.md directly — pending fragments are folded into it at release time.

Breaking Changes

None. The action is off by default; behavior is unchanged unless explicitly enabled.

Additional Notes

  • Unit tests: pkg/scheduler/actions/resizeeviction/resizeeviction_test.go (preempt/reclaim eligibility, all-or-nothing, gang victims, multi-deferred shortfall exclusion, already-enactable no-op) and pkg/scheduler/api/pod_info/resize_test.go (condition generation-awareness, delta computation).
  • E2E: test/e2e/suites/resize/deferred_eviction_test.go enables the action on the default shard, drives a real pods/resize into Deferred, and asserts the victim is evicted and the resize enacts.
  • Known limitations are listed in the design doc: elastic victims whose next evictable task is on another node are skipped rather than retargeted, and victim search is greedy in victim-queue order rather than minimal-set scenario search.

gshaibi and others added 30 commits August 5, 2026 20:49
Adds design document for effective-request accounting and best-effort
webhook admission for in-place pod resizes. Fixes #1906.

Signed-off-by: gshaibi <gshaibi@nvidia.com>
…nd queue admission

Implements the design from PR #1997:

1. Effective-request accounting (KEP-1287):
   - Preserve ContainerStatus.Resources and AllocatedResources in the
     scheduler informer compact transform (pod_transform.go) so resize
     state is visible to the scheduler.
   - Compute effective pod requests as max(spec, enacted, allocated) per
     container; exclude spec when PodResizePending=Infeasible so infeasible
     resize targets do not inflate accounting.

2. Best-effort pods/resize admission webhook:
   - New PodResizeValidator validates pods/resize subresource updates.
   - Computes delta = max(proposed - old spec, 0) and rejects if any queue
     on the hierarchy would exceed its CPU/memory limit (all workloads) or
     CPU/memory quota (non-preemptible workloads).
   - failurePolicy=ignore so webhook unavailability never blocks a resize.

Signed-off-by: gshaibi <gshaibi@nvidia.com>
Signed-off-by: gshaibi <gshaibi@nvidia.com>
Signed-off-by: gshaibi <gshaibi@nvidia.com>
- operator: add pods/resize webhook entry (failurePolicy=Ignore) to
  validatingWCForKAIConfig so the handler is reachable in production
- admission: register scheduling/v2 (Queue) and scheduling/v2alpha2
  (PodGroup) in the manager scheme; add RBAC markers for PodGroups,
  Queues, and PriorityClasses so the client can fetch them at runtime
- scheduler: guard isPodResizeInfeasible with Status==ConditionTrue to
  avoid acting on a stale or transitional condition
- admission: replace specPodRequests delta with per-resource, per-container
  delta using max(enacted, allocated) as the effective-old baseline; skip
  resources unchanged in this resize so a stale infeasible spec target does
  not produce a spurious delta
- admission: treat quota==0 as a finite boundary (use >= 0, matching the
  limit check) so non-preemptible upsizes are blocked when quota is zero
- scheduler: apply the KEP-1287 effective-request model to restartable
  init containers (native sidecars) in initContainerEffects so a sidecar
  downsize in progress is not undercounted

Signed-off-by: gshaibi <gshaibi@nvidia.com>
…pod resize validator

- Add InPlacePodResize config struct to Admission API with ValidateQuota and
  BlockUpsizeOnBoundedQueues fields (defaults: true / false)
- Add --validate-pod-resize-quota and --block-upsize-on-bounded-queues CLI flags
- Wire flags from operator buildArgsList through to PodResizeValidator constructor
- validateQuota=false: early-return allows all resizes without quota checks
- blockUpsizeOnBoundedQueues=true: reject any upsize on queues with finite limit
  (all workloads) or finite quota (non-preemptible), regardless of allocation
- Add tests covering both new modes

Signed-off-by: gshaibi <gshaibi@nvidia.com>
…ake validate

- Fix import ordering in app.go (goimports sort)
- Fix struct field alignment in options.go (gofmt)
- Remove trailing blank line in effective_requests.go
- Regenerate CRD with inPlacePodResize fields
- Regenerate admission RBAC with queues/podgroups/priorityclasses rules

Signed-off-by: gshaibi <gshaibi@nvidia.com>
…ine, and redistribution

Three bugs in podResizeDelta addressed:

- Sidecar upsizes bypassed admission: now iterates restartable init containers
  (RestartPolicy=Always) using InitContainerStatuses, matching the scheduler's
  initContainerEffects accounting.

- Non-infeasible old spec was excluded from baseline: for normal/Deferred/InProgress
  pods the queue accounts for max(spec, enacted, allocated); the webhook now mirrors
  this instead of always using only max(enacted, allocated).

- Per-container aggregation counted redistribution as growth: moving CPU from
  container A to container B produced a positive delta. Switched to pod-level
  aggregation (sum across all containers before diffing).

The new structure: accumulate newSpecSum, oldSpecSum, effectiveOldSum at the pod
level; skip a resource if newSpecSum[r] == oldSpecSum[r] (unchanged by this resize);
delta = max(0, newSpecSum[r] - effectiveOldSum[r]).

Add three tests: sidecar denied, non-infeasible baseline, redistribution allowed.

Signed-off-by: gshaibi <gshaibi@nvidia.com>
…entation-2f767b

# Conflicts:
#	pkg/operator/operands/admission/resources.go
#	pkg/scheduler/cache/pod_transform.go

Signed-off-by: gshaibi <gshaibi@nvidia.com>
Signed-off-by: gshaibi <gshaibi@nvidia.com>
…helpers

Replaces hand-rolled KEP-1287 aggregation with upstream
resource.AggregateContainerRequests(UseStatusResources: true).

- delete effective_requests.go entirely (3 funcs -> upstream)
- collapse getPodResourceWithoutInitContainers + initContainerEffects
  into a single upstream call
- webhook uses resource.IsPodResizeInfeasible instead of a local copy
- retarget effective-request tests at the public aggregation path

KNOWN FAILURE: upstream IsPodResizeInfeasible does not check
condition.Status == True, so a stale Infeasible condition with
Status=False is treated as infeasible.

Signed-off-by: gshaibi <gshaibi@nvidia.com>
Signed-off-by: gshaibi <gshaibi@nvidia.com>
…ion test

Upstream keys off Reason alone and ignores condition.Status, so the
Status==True guard added in #2021 does not survive the move to
k8s.io/component-helpers.

Accepts upstream semantics and pins the difference so a future upstream
tightening surfaces as a test failure rather than a silent change.

Signed-off-by: gshaibi <gshaibi@nvidia.com>
…helpers-prototype

refactor(scheduler): delegate effective-request accounting to k8s.io/component-helpers
…entation-2f767b

Signed-off-by: gshaibi <gshaibi@nvidia.com>
…unting_test.go

The effective_requests.go source it was named after was removed when
aggregation moved to k8s.io/component-helpers. The tests now cover KAI's
wiring of the upstream helper through getPodResourceRequest.

Signed-off-by: gshaibi <gshaibi@nvidia.com>
…cePodVerticalScaling

Signed-off-by: gshaibi <gshaibi@nvidia.com>
…g hierarchy

- compactResizeConditions -> compactConditions, matching sibling naming
  (functions are named for the field they compact); drop stale
  'generation-aware' wording
- document that BlockUpsizeOnBoundedQueues has no effect when
  ValidateQuota is false, in API comments, CLI flag help, and CRD

Signed-off-by: gshaibi <gshaibi@nvidia.com>
…cated resources

Queue.Status.Allocated is derived from PodGroup.Status.ResourcesStatus.Allocated,
which summed raw pod spec requests. An Infeasible resize target therefore inflated
queue allocated (e.g. a rejected 64-CPU resize charged 64 CPU), diverging from
scheduler-internal accounting and double-counting in the resize webhook's limit
check. Found by live-cluster testing.

Switch to the same upstream aggregation the scheduler uses
(AggregateContainerRequests): KEP-1287 effective requests for allocated
(UseStatusResources), spec-only for requested. This also closes a pre-existing
undercount: init-phase peak and sidecars now count toward podgroup/queue
allocated, matching what the scheduler has always reserved internally.

Signed-off-by: gshaibi <gshaibi@nvidia.com>
…tion, dedup capacity checks

Move IsPreemptible (with its PriorityClass fallback chain: specific -> global
default -> DefaultPodGroupPriority) from podgroupcontroller utilities to
pkg/common/podgroup, and use it in the resize webhook instead of a divergent
local resolver. The webhook assumed priority 0 for unset/missing priority
classes while the controller fell back to defaults - so a pod counted in
AllocatedNonPreemptible could skip the webhook's quota check entirely.
The checker and the accountant now share one implementation.

Merge checkLimit and checkNonPreemptibleQuota into checkCapacityBound,
parameterized by bound and allocated pool. The earlier quota>0 vs limit>=0
sentinel bug was drift between these two copies.

Signed-off-by: gshaibi <gshaibi@nvidia.com>
E2E suite (test/e2e/suites/resize/) covers the resize admission webhook
(deny past queue limit, allow within, downsizes) and effective-request
accounting end to end (infeasible resize target must not inflate
Queue.status.allocated). Skips on clusters older than 1.33. Resize calls
retry on conflict: the kubelet writes pod status concurrently during a
resize.

User docs (docs/in-place-resize/) cover the effective-request charging
model, webhook semantics including best-effort fail-open behavior, and
the inPlacePodResize config fields.

Signed-off-by: gshaibi <gshaibi@nvidia.com>
Signed-off-by: gshaibi <gshaibi@nvidia.com>
GetConnectivity stores the calling node's context; ginkgo cancels it when
the node exits, so a TestContext created in BeforeEach fails every client
call from the It body with 'context canceled'. Follow the quota-suite
pattern: connectivity, skips, and cleanup live inside each spec.

Signed-off-by: gshaibi <gshaibi@nvidia.com>
Replace the raw admission.Handler with the generic admission.Validator[*corev1.Pod]
and register through the webhook builder with WithValidatorCustomPath, matching
the sibling webhooks. The custom path is still required: the canonical
/validate--v1-pod path belongs to the general pod validator.

Removes the manual decoder, the scheme constructor parameter, and the
request-encoding helpers in tests, which now call ValidateUpdate directly.

Signed-off-by: gshaibi <gshaibi@nvidia.com>
Signed-off-by: gshaibi <gshaibi@nvidia.com>
…t guarantee

Signed-off-by: gshaibi <gshaibi@nvidia.com>
…resizes

Signed-off-by: gshaibi <gshaibi@nvidia.com>
Remove comments that restate the code (capacity-check section headers,
inline continue/return annotations) and compress multi-line rationales
to their load-bearing sentences.

Signed-off-by: gshaibi <gshaibi@nvidia.com>
.
Signed-off-by: gshaibi <gshaibi@nvidia.com>
…nt charge

Found during manual testing: a follow-up upsize issued before the kubelet
enacts a pending downsize is compared against the transient (still-charged)
value and can settle above the queue limit.

Signed-off-by: gshaibi <gshaibi@nvidia.com>
Signed-off-by: gshaibi <gshaibi@nvidia.com>
Signed-off-by: gshaibi <gshaibi@nvidia.com>
Detect pods whose in-place resize the kubelet marked Deferred and evict
victims on their node so the resize can be enacted. Victim eligibility
mirrors a new pod of that size: same-queue preempt rules by priority,
cross-queue reclaim rules gated on fair share, validated by the same
scenario validators. All-or-nothing per resizing pod.

The action is registered but not part of the default actions list.

Part of #1872

Signed-off-by: gshaibi <gshaibi@nvidia.com>
Default priority 150 (after preempt); enabled per shard via
spec.actions.resizeeviction.enabled.

Part of #1872

Signed-off-by: gshaibi <gshaibi@nvidia.com>
Part of #1872

Signed-off-by: gshaibi <gshaibi@nvidia.com>
Part of #1872

Signed-off-by: gshaibi <gshaibi@nvidia.com>
gshaibi added a commit that referenced this pull request Aug 10, 2026
…erred charge as a contract

Generation-aware Infeasible was rejected during implementation (the
observedGeneration field requires a non-GA gate; upstream reason-only
semantics adopted and pinned by a characterization test) - update the
design to match. Note that the Deferred max(spec, actual) charge is a
dependency of deferred-resize eviction (#1872 / #2051): the reserved
target prevents backfill thrash after victim eviction.

Signed-off-by: gshaibi <gshaibi@nvidia.com>
@github-actions

Copy link
Copy Markdown

📊 Performance Benchmark Results

Comparing PR (feat/deferred-resize-eviction) vs main branch — click to expand
goos: linux
goarch: amd64
pkg: github.com/kai-scheduler/KAI-scheduler/pkg/scheduler/actions
cpu: INTEL(R) XEON(R) PLATINUM 8573C
                                    │ main-bench.txt │           pr-bench.txt            │
                                    │     sec/op     │   sec/op     vs base              │
AllocateAction_SmallCluster-4            107.7m ± 0%   107.6m ± 8%       ~ (p=0.937 n=6)
AllocateAction_MediumCluster-4           130.3m ± 1%   130.2m ± 0%       ~ (p=0.818 n=6)
AllocateAction_LargeCluster-4            191.5m ± 2%   189.3m ± 1%       ~ (p=0.065 n=6)
ReclaimAction_SmallCluster-4             103.3m ± 0%   103.4m ± 0%       ~ (p=0.937 n=6)
ReclaimAction_MediumCluster-4            106.3m ± 1%   106.7m ± 1%       ~ (p=0.132 n=6)
PreemptAction_SmallCluster-4             104.6m ± 0%   104.5m ± 0%       ~ (p=0.240 n=6)
PreemptAction_MediumCluster-4            113.8m ± 1%   113.1m ± 1%  -0.67% (p=0.041 n=6)
ConsolidationAction_SmallCluster-4       121.2m ± 1%   120.6m ± 0%       ~ (p=0.132 n=6)
ConsolidationAction_MediumCluster-4      260.3m ± 1%   259.9m ± 2%       ~ (p=0.394 n=6)
FullSchedulingCycle_SmallCluster-4       105.9m ± 0%   105.7m ± 0%       ~ (p=0.394 n=6)
FullSchedulingCycle_MediumCluster-4      117.9m ± 2%   117.2m ± 1%  -0.54% (p=0.041 n=6)
FullSchedulingCycle_LargeCluster-4       152.3m ± 2%   151.2m ± 1%  -0.77% (p=0.041 n=6)
ManyQueues_MediumCluster-4               133.8m ± 1%   133.1m ± 1%       ~ (p=0.310 n=6)
GangScheduling_MediumCluster-4           150.2m ± 2%   151.1m ± 1%       ~ (p=0.589 n=6)
geomean                                  130.7m        130.3m       -0.25%

                                    │ main-bench.txt │            pr-bench.txt             │
                                    │      B/op      │     B/op       vs base              │
AllocateAction_SmallCluster-4           2.076Mi ± 0%    2.109Mi ± 1%  +1.58% (p=0.002 n=6)
AllocateAction_MediumCluster-4          9.902Mi ± 0%   10.027Mi ± 0%  +1.26% (p=0.002 n=6)
AllocateAction_LargeCluster-4           31.27Mi ± 0%    31.57Mi ± 0%  +0.93% (p=0.002 n=6)
ReclaimAction_SmallCluster-4            955.4Ki ± 0%    970.3Ki ± 1%  +1.55% (p=0.002 n=6)
ReclaimAction_MediumCluster-4           3.106Mi ± 0%    3.164Mi ± 0%  +1.87% (p=0.002 n=6)
PreemptAction_SmallCluster-4            1.343Mi ± 0%    1.369Mi ± 1%  +1.96% (p=0.002 n=6)
PreemptAction_MediumCluster-4           5.934Mi ± 0%    6.029Mi ± 0%  +1.60% (p=0.002 n=6)
ConsolidationAction_SmallCluster-4      8.205Mi ± 0%    8.227Mi ± 0%  +0.27% (p=0.002 n=6)
ConsolidationAction_MediumCluster-4     67.76Mi ± 0%    67.85Mi ± 0%  +0.14% (p=0.002 n=6)
FullSchedulingCycle_SmallCluster-4      1.405Mi ± 1%    1.436Mi ± 1%  +2.19% (p=0.002 n=6)
FullSchedulingCycle_MediumCluster-4     6.140Mi ± 0%    6.231Mi ± 0%  +1.48% (p=0.002 n=6)
FullSchedulingCycle_LargeCluster-4      18.36Mi ± 0%    18.59Mi ± 0%  +1.25% (p=0.002 n=6)
ManyQueues_MediumCluster-4              13.13Mi ± 0%    13.25Mi ± 0%  +0.90% (p=0.002 n=6)
GangScheduling_MediumCluster-4          15.33Mi ± 0%    15.57Mi ± 0%  +1.60% (p=0.002 n=6)
geomean                                 6.542Mi         6.629Mi       +1.33%

                                    │ main-bench.txt │           pr-bench.txt            │
                                    │   allocs/op    │  allocs/op   vs base              │
AllocateAction_SmallCluster-4            31.49k ± 0%   30.99k ± 0%  -1.59% (p=0.002 n=6)
AllocateAction_MediumCluster-4           245.8k ± 0%   243.8k ± 0%  -0.81% (p=0.002 n=6)
AllocateAction_LargeCluster-4            1.007M ± 0%   1.002M ± 0%  -0.50% (p=0.002 n=6)
ReclaimAction_SmallCluster-4             8.937k ± 0%   8.686k ± 0%  -2.81% (p=0.002 n=6)
ReclaimAction_MediumCluster-4            28.12k ± 0%   27.12k ± 0%  -3.55% (p=0.002 n=6)
PreemptAction_SmallCluster-4             15.27k ± 0%   14.89k ± 0%  -2.45% (p=0.002 n=6)
PreemptAction_MediumCluster-4            55.29k ± 0%   53.79k ± 0%  -2.71% (p=0.002 n=6)
ConsolidationAction_SmallCluster-4       109.7k ± 0%   109.3k ± 0%  -0.35% (p=0.002 n=6)
ConsolidationAction_MediumCluster-4      1.020M ± 0%   1.019M ± 0%  -0.15% (p=0.002 n=6)
FullSchedulingCycle_SmallCluster-4       19.63k ± 0%   19.26k ± 0%  -1.92% (p=0.002 n=6)
FullSchedulingCycle_MediumCluster-4      136.3k ± 0%   134.8k ± 0%  -1.09% (p=0.002 n=6)
FullSchedulingCycle_LargeCluster-4       537.7k ± 0%   533.9k ± 0%  -0.70% (p=0.002 n=6)
ManyQueues_MediumCluster-4               274.0k ± 0%   272.0k ± 0%  -0.73% (p=0.002 n=6)
GangScheduling_MediumCluster-4           455.3k ± 0%   451.4k ± 0%  -0.87% (p=0.002 n=6)
geomean                                  109.0k        107.4k       -1.45%

pkg: github.com/kai-scheduler/KAI-scheduler/pkg/scheduler/actions/integration_tests/reclaim
                                                          │ main-bench.txt │            pr-bench.txt             │
                                                          │     sec/op     │    sec/op     vs base               │
ReclaimLargeJobs_10Node-4                                     137.2m ±  1%   137.5m ±  0%        ~ (p=0.065 n=6)
ReclaimLargeJobs_50Node-4                                     317.6m ±  1%   317.6m ±  1%        ~ (p=0.937 n=6)
ReclaimLargeJobs_100Node-4                                    624.3m ±  7%   633.3m ±  7%        ~ (p=0.240 n=6)
ReclaimLargeJobs_200Node-4                                     1.500 ±  1%    1.514 ±  1%        ~ (p=0.093 n=6)
ReclaimLargeJobs_500Node-4                                     6.288 ±  1%    6.207 ±  1%   -1.29% (p=0.041 n=6)
ReclaimLargeJobs_1000Node-4                                    25.47 ±  1%    25.35 ±  1%        ~ (p=0.394 n=6)
ReclaimManySingleGPUJobsFullCycle_10Node-4                    151.7m ±  1%   151.9m ±  1%        ~ (p=0.589 n=6)
ReclaimManySingleGPUJobsFullCycle_50Node-4                    919.8m ±  0%   925.6m ±  1%   +0.63% (p=0.015 n=6)
ReclaimManySingleGPUJobsFullCycle_100Node-4                    3.387 ±  1%    3.414 ±  0%   +0.79% (p=0.009 n=6)
ReclaimManySingleGPUJobsFullCycle_200Node-4                    13.65 ±  1%    13.77 ±  1%        ~ (p=0.093 n=6)
ReclaimManySingleGPUJobsFullCycle_500Node-4                    99.24 ± 19%   117.27 ± 14%  +18.17% (p=0.015 n=6)
ReclaimManySingleGPUJobsFullCycleWithMinRuntime_500Node-4      92.93 ±  7%   113.60 ± 12%  +22.24% (p=0.002 n=6)
geomean                                                        2.923          3.022         +3.40%

                                                          │ main-bench.txt │            pr-bench.txt            │
                                                          │      B/op      │     B/op      vs base              │
ReclaimLargeJobs_10Node-4                                     17.19Mi ± 1%   17.23Mi ± 1%       ~ (p=0.065 n=6)
ReclaimLargeJobs_50Node-4                                     91.84Mi ± 0%   92.04Mi ± 0%  +0.22% (p=0.002 n=6)
ReclaimLargeJobs_100Node-4                                    204.2Mi ± 0%   204.7Mi ± 0%  +0.21% (p=0.002 n=6)
ReclaimLargeJobs_200Node-4                                    486.1Mi ± 0%   487.0Mi ± 0%  +0.18% (p=0.002 n=6)
ReclaimLargeJobs_500Node-4                                    1.698Gi ± 0%   1.700Gi ± 0%  +0.12% (p=0.002 n=6)
ReclaimLargeJobs_1000Node-4                                   5.141Gi ± 0%   5.145Gi ± 0%  +0.08% (p=0.002 n=6)
ReclaimManySingleGPUJobsFullCycle_10Node-4                    14.81Mi ± 0%   14.91Mi ± 0%  +0.67% (p=0.002 n=6)
ReclaimManySingleGPUJobsFullCycle_50Node-4                    145.0Mi ± 0%   145.5Mi ± 0%  +0.36% (p=0.002 n=6)
ReclaimManySingleGPUJobsFullCycle_100Node-4                   470.5Mi ± 0%   471.6Mi ± 0%  +0.22% (p=0.002 n=6)
ReclaimManySingleGPUJobsFullCycle_200Node-4                   1.629Gi ± 0%   1.631Gi ± 0%  +0.12% (p=0.002 n=6)
ReclaimManySingleGPUJobsFullCycle_500Node-4                   10.34Gi ± 0%   10.35Gi ± 0%  +0.04% (p=0.002 n=6)
ReclaimManySingleGPUJobsFullCycleWithMinRuntime_500Node-4     10.34Gi ± 0%   10.35Gi ± 0%  +0.04% (p=0.002 n=6)
geomean                                                       504.4Mi        505.4Mi       +0.21%

                                                          │ main-bench.txt │           pr-bench.txt            │
                                                          │   allocs/op    │  allocs/op   vs base              │
ReclaimLargeJobs_10Node-4                                      242.0k ± 0%   241.4k ± 0%  -0.27% (p=0.037 n=6)
ReclaimLargeJobs_50Node-4                                      1.482M ± 0%   1.478M ± 0%  -0.22% (p=0.002 n=6)
ReclaimLargeJobs_100Node-4                                     3.741M ± 0%   3.735M ± 0%  -0.17% (p=0.002 n=6)
ReclaimLargeJobs_200Node-4                                     10.52M ± 0%   10.51M ± 0%  -0.12% (p=0.002 n=6)
ReclaimLargeJobs_500Node-4                                     45.58M ± 0%   45.54M ± 0%  -0.07% (p=0.002 n=6)
ReclaimLargeJobs_1000Node-4                                    159.5M ± 0%   159.4M ± 0%  -0.04% (p=0.002 n=6)
ReclaimManySingleGPUJobsFullCycle_10Node-4                     279.9k ± 0%   278.3k ± 0%  -0.57% (p=0.002 n=6)
ReclaimManySingleGPUJobsFullCycle_50Node-4                     3.741M ± 0%   3.733M ± 0%  -0.21% (p=0.002 n=6)
ReclaimManySingleGPUJobsFullCycle_100Node-4                    13.33M ± 0%   13.32M ± 0%  -0.12% (p=0.002 n=6)
ReclaimManySingleGPUJobsFullCycle_200Node-4                    50.07M ± 0%   50.03M ± 0%  -0.06% (p=0.002 n=6)
ReclaimManySingleGPUJobsFullCycle_500Node-4                    300.6M ± 0%   300.5M ± 0%  -0.03% (p=0.002 n=6)
ReclaimManySingleGPUJobsFullCycleWithMinRuntime_500Node-4      300.6M ± 0%   300.5M ± 0%  -0.03% (p=0.002 n=6)
geomean                                                        11.69M        11.67M       -0.16%

                                                          │ main-bench.txt │              pr-bench.txt              │
                                                          │ full_cycles/op │ full_cycles/op  vs base                │
ReclaimManySingleGPUJobsFullCycle_10Node-4                      1.000 ± 0%       1.000 ± 0%       ~ (p=1.000 n=6) ¹
ReclaimManySingleGPUJobsFullCycle_50Node-4                      1.000 ± 0%       1.000 ± 0%       ~ (p=1.000 n=6) ¹
ReclaimManySingleGPUJobsFullCycle_100Node-4                     1.000 ± 0%       1.000 ± 0%       ~ (p=1.000 n=6) ¹
ReclaimManySingleGPUJobsFullCycle_200Node-4                     1.000 ± 0%       1.000 ± 0%       ~ (p=1.000 n=6) ¹
ReclaimManySingleGPUJobsFullCycle_500Node-4                     1.000 ± 0%       1.000 ± 0%       ~ (p=1.000 n=6) ¹
ReclaimManySingleGPUJobsFullCycleWithMinRuntime_500Node-4       1.000 ± 0%       1.000 ± 0%       ~ (p=1.000 n=6) ¹
geomean                                                         1.000            1.000       +0.00%
¹ all samples are equal

                                            │          main-bench.txt           │                     pr-bench.txt                     │
                                            │ fit_error_tasks_after_allocate/op │ fit_error_tasks_after_allocate/op  vs base           │
ReclaimManySingleGPUJobsFullCycle_500Node-4                         4.000k ± 0%                         4.000k ± 0%  ~ (p=1.000 n=6) ¹
¹ all samples are equal

                                            │          main-bench.txt           │                    pr-bench.txt                    │
                                            │ heap_live_after_allocate_bytes/op │ heap_live_after_allocate_bytes/op  vs base         │
ReclaimManySingleGPUJobsFullCycle_500Node-4                        41.55M ± 76%                        41.55M ± 76%  ~ (p=1.000 n=6)

                                            │         main-bench.txt         │                  pr-bench.txt                   │
                                            │ heap_live_after_cycle_bytes/op │ heap_live_after_cycle_bytes/op  vs base         │
ReclaimManySingleGPUJobsFullCycle_500Node-4                     56.18M ± 56%                     56.16M ± 56%  ~ (p=0.589 n=6)

pkg: github.com/kai-scheduler/KAI-scheduler/pkg/scheduler/actions/preempt
                                  │ main-bench.txt │           pr-bench.txt            │
                                  │     sec/op     │   sec/op     vs base              │
OrderedVictimsQueueConstruction-4      636.0µ ± 1%   647.4µ ± 0%  +1.79% (p=0.002 n=6)

                                  │ main-bench.txt │          pr-bench.txt           │
                                  │      B/op      │     B/op      vs base           │
OrderedVictimsQueueConstruction-4     114.9Ki ± 0%   114.9Ki ± 0%  ~ (p=1.000 n=6) ¹
¹ all samples are equal

                                  │ main-bench.txt │          pr-bench.txt          │
                                  │   allocs/op    │  allocs/op   vs base           │
OrderedVictimsQueueConstruction-4      4.033k ± 0%   4.033k ± 0%  ~ (p=1.000 n=6) ¹
¹ all samples are equal

pkg: github.com/kai-scheduler/KAI-scheduler/pkg/scheduler/actions/reclaim
                                                         │ main-bench.txt │           pr-bench.txt            │
                                                         │     sec/op     │   sec/op     vs base              │
ReclaimUnschedulableDistributedJob_10Node-4                   148.7m ± 2%   148.1m ± 1%       ~ (p=0.310 n=6)
ReclaimUnschedulableDistributedJob_50Node-4                    3.242 ± 2%    3.237 ± 3%       ~ (p=1.000 n=6)
ReclaimUnschedulableDistributedJob_100Node-4                   15.95 ± 2%    16.33 ± 1%  +2.40% (p=0.002 n=6)
ReclaimUnschedulableDistributedJob_AntiAffinity100Node-4       14.29 ± 2%    14.83 ± 1%  +3.77% (p=0.002 n=6)
ReclaimWithMissingPVCJobs-4                                   2.678m ± 1%   2.715m ± 6%       ~ (p=0.240 n=6)
geomean                                                       783.0m        793.8m       +1.38%

                                                         │ main-bench.txt │            pr-bench.txt            │
                                                         │      B/op      │     B/op      vs base              │
ReclaimUnschedulableDistributedJob_10Node-4                  20.89Mi ± 3%   20.91Mi ± 3%       ~ (p=0.699 n=6)
ReclaimUnschedulableDistributedJob_50Node-4                  1.154Gi ± 0%   1.154Gi ± 0%       ~ (p=0.485 n=6)
ReclaimUnschedulableDistributedJob_100Node-4                 5.559Gi ± 0%   5.560Gi ± 0%       ~ (p=0.240 n=6)
ReclaimUnschedulableDistributedJob_AntiAffinity100Node-4     5.159Gi ± 0%   5.159Gi ± 0%       ~ (p=0.699 n=6)
ReclaimWithMissingPVCJobs-4                                  9.023Ki ± 2%   8.898Ki ± 2%       ~ (p=0.197 n=6)
geomean                                                      91.87Mi        91.63Mi       -0.26%

                                                         │ main-bench.txt │           pr-bench.txt            │
                                                         │   allocs/op    │  allocs/op   vs base              │
ReclaimUnschedulableDistributedJob_10Node-4                   306.1k ± 3%   305.2k ± 3%  -0.28% (p=0.037 n=6)
ReclaimUnschedulableDistributedJob_50Node-4                   27.77M ± 0%   27.76M ± 0%  -0.02% (p=0.002 n=6)
ReclaimUnschedulableDistributedJob_100Node-4                  169.0M ± 0%   169.0M ± 0%  -0.01% (p=0.002 n=6)
ReclaimUnschedulableDistributedJob_AntiAffinity100Node-4      146.8M ± 0%   146.8M ± 0%       ~ (p=0.065 n=6)
ReclaimWithMissingPVCJobs-4                                    170.0 ± 1%    169.0 ± 1%       ~ (p=0.197 n=6)
geomean                                                       2.046M        2.042M       -0.18%

                                                         │ main-bench.txt │             pr-bench.txt             │
                                                         │  duplicate/op  │ duplicate/op  vs base                │
ReclaimUnschedulableDistributedJob_10Node-4                  0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=6) ¹
ReclaimUnschedulableDistributedJob_50Node-4                  366.0 ± 0%       366.0 ± 0%       ~ (p=1.000 n=6) ¹
ReclaimUnschedulableDistributedJob_100Node-4                1.020k ± 0%      1.020k ± 0%       ~ (p=1.000 n=6) ¹
ReclaimUnschedulableDistributedJob_AntiAffinity100Node-4    1.020k ± 0%      1.020k ± 0%       ~ (p=1.000 n=6) ¹
geomean                                                                 ²                 +0.00%               ²
¹ all samples are equal
² summaries must be >0 to compute geomean

                                                         │ main-bench.txt │             pr-bench.txt             │
                                                         │  simulated/op  │ simulated/op  vs base                │
ReclaimUnschedulableDistributedJob_10Node-4                    18.00 ± 0%     18.00 ± 0%       ~ (p=1.000 n=6) ¹
ReclaimUnschedulableDistributedJob_50Node-4                    178.0 ± 0%     178.0 ± 0%       ~ (p=1.000 n=6) ¹
ReclaimUnschedulableDistributedJob_100Node-4                   378.0 ± 0%     378.0 ± 0%       ~ (p=1.000 n=6) ¹
ReclaimUnschedulableDistributedJob_AntiAffinity100Node-4       378.0 ± 0%     378.0 ± 0%       ~ (p=1.000 n=6) ¹
geomean                                                        146.3          146.3       +0.00%
¹ all samples are equal

Legend

  • 📉 Negative delta = Performance improvement (faster)
  • 📈 Positive delta = Performance regression (slower)
  • p-value < 0.05 indicates statistically significant change
Raw benchmark data

PR branch:

goos: linux
goarch: amd64
pkg: github.com/kai-scheduler/KAI-scheduler/pkg/scheduler/actions
cpu: INTEL(R) XEON(R) PLATINUM 8573C
BenchmarkAllocateAction_SmallCluster-4         	       9	 115991053 ns/op	 2221697 B/op	   30992 allocs/op
BenchmarkAllocateAction_SmallCluster-4         	      10	 110747345 ns/op	 2223428 B/op	   30995 allocs/op
BenchmarkAllocateAction_SmallCluster-4         	      10	 107636524 ns/op	 2207314 B/op	   30988 allocs/op
BenchmarkAllocateAction_SmallCluster-4         	      10	 107469688 ns/op	 2203499 B/op	   30983 allocs/op
BenchmarkAllocateAction_SmallCluster-4         	      10	 107515597 ns/op	 2214545 B/op	   30981 allocs/op
BenchmarkAllocateAction_SmallCluster-4         	      10	 107565478 ns/op	 2205204 B/op	   30992 allocs/op
BenchmarkAllocateAction_MediumCluster-4        	       8	 130714639 ns/op	10529711 B/op	  243776 allocs/op
BenchmarkAllocateAction_MediumCluster-4        	       8	 130307586 ns/op	10523169 B/op	  243769 allocs/op
BenchmarkAllocateAction_MediumCluster-4        	       8	 129796138 ns/op	10515319 B/op	  243787 allocs/op
BenchmarkAllocateAction_MediumCluster-4        	       8	 130463580 ns/op	10512301 B/op	  243809 allocs/op
BenchmarkAllocateAction_MediumCluster-4        	       8	 130158796 ns/op	10510211 B/op	  243786 allocs/op
BenchmarkAllocateAction_MediumCluster-4        	       8	 130126486 ns/op	10512310 B/op	  243783 allocs/op
BenchmarkAllocateAction_LargeCluster-4         	       6	 191344780 ns/op	33096445 B/op	 1002217 allocs/op
BenchmarkAllocateAction_LargeCluster-4         	       6	 188674245 ns/op	33095086 B/op	 1002146 allocs/op
BenchmarkAllocateAction_LargeCluster-4         	       6	 189310232 ns/op	33100440 B/op	 1002161 allocs/op
BenchmarkAllocateAction_LargeCluster-4         	       6	 189296520 ns/op	33096434 B/op	 1002197 allocs/op
BenchmarkAllocateAction_LargeCluster-4         	       6	 188070006 ns/op	33112340 B/op	 1002207 allocs/op
BenchmarkAllocateAction_LargeCluster-4         	       6	 189921235 ns/op	33110924 B/op	 1002207 allocs/op
BenchmarkReclaimAction_SmallCluster-4          	      10	 103273029 ns/op	  993156 B/op	    8685 allocs/op
BenchmarkReclaimAction_SmallCluster-4          	      10	 103325450 ns/op	  993917 B/op	    8686 allocs/op
BenchmarkReclaimAction_SmallCluster-4          	      10	 103446757 ns/op	  990608 B/op	    8686 allocs/op
BenchmarkReclaimAction_SmallCluster-4          	      10	 103309539 ns/op	  994298 B/op	    8687 allocs/op
BenchmarkReclaimAction_SmallCluster-4          	      10	 103530013 ns/op	  986688 B/op	    8685 allocs/op
BenchmarkReclaimAction_SmallCluster-4          	      10	 103412361 ns/op	  994301 B/op	    8687 allocs/op
BenchmarkReclaimAction_MediumCluster-4         	      10	 106806440 ns/op	 3317870 B/op	   27120 allocs/op
BenchmarkReclaimAction_MediumCluster-4         	      10	 106975213 ns/op	 3318286 B/op	   27118 allocs/op
BenchmarkReclaimAction_MediumCluster-4         	      10	 106647196 ns/op	 3317832 B/op	   27120 allocs/op
BenchmarkReclaimAction_MediumCluster-4         	      10	 106638776 ns/op	 3316796 B/op	   27118 allocs/op
BenchmarkReclaimAction_MediumCluster-4         	      10	 106334134 ns/op	 3317244 B/op	   27120 allocs/op
BenchmarkReclaimAction_MediumCluster-4         	      10	 107676034 ns/op	 3320961 B/op	   27120 allocs/op
BenchmarkPreemptAction_SmallCluster-4          	      10	 104537244 ns/op	 1436159 B/op	   14896 allocs/op
BenchmarkPreemptAction_SmallCluster-4          	      10	 104566090 ns/op	 1435868 B/op	   14893 allocs/op
BenchmarkPreemptAction_SmallCluster-4          	      10	 104448650 ns/op	 1435802 B/op	   14894 allocs/op
BenchmarkPreemptAction_SmallCluster-4          	      10	 104403910 ns/op	 1428092 B/op	   14891 allocs/op
BenchmarkPreemptAction_SmallCluster-4          	      10	 104511982 ns/op	 1432373 B/op	   14893 allocs/op
BenchmarkPreemptAction_SmallCluster-4          	      10	 104421913 ns/op	 1435775 B/op	   14894 allocs/op
BenchmarkPreemptAction_MediumCluster-4         	       9	 113316583 ns/op	 6323223 B/op	   53793 allocs/op
BenchmarkPreemptAction_MediumCluster-4         	       9	 112660289 ns/op	 6324893 B/op	   53795 allocs/op
BenchmarkPreemptAction_MediumCluster-4         	       9	 114634118 ns/op	 6307935 B/op	   53791 allocs/op
BenchmarkPreemptAction_MediumCluster-4         	       9	 113171078 ns/op	 6324313 B/op	   53793 allocs/op
BenchmarkPreemptAction_MediumCluster-4         	       9	 112969072 ns/op	 6320312 B/op	   53793 allocs/op
BenchmarkPreemptAction_MediumCluster-4         	       9	 112800531 ns/op	 6320317 B/op	   53793 allocs/op
BenchmarkConsolidationAction_SmallCluster-4    	       9	 120620483 ns/op	 8627256 B/op	  109288 allocs/op
BenchmarkConsolidationAction_SmallCluster-4    	       9	 120655697 ns/op	 8626244 B/op	  109285 allocs/op
BenchmarkConsolidationAction_SmallCluster-4    	       9	 120823332 ns/op	 8626867 B/op	  109286 allocs/op
BenchmarkConsolidationAction_SmallCluster-4    	       9	 120285440 ns/op	 8626460 B/op	  109285 allocs/op

Main branch:

goos: linux
goarch: amd64
pkg: github.com/kai-scheduler/KAI-scheduler/pkg/scheduler/actions
cpu: INTEL(R) XEON(R) PLATINUM 8573C
BenchmarkAllocateAction_SmallCluster-4         	      10	 107619804 ns/op	 2172040 B/op	   31488 allocs/op
BenchmarkAllocateAction_SmallCluster-4         	      10	 107183688 ns/op	 2172242 B/op	   31490 allocs/op
BenchmarkAllocateAction_SmallCluster-4         	      10	 107685088 ns/op	 2172688 B/op	   31491 allocs/op
BenchmarkAllocateAction_SmallCluster-4         	      10	 108004713 ns/op	 2186666 B/op	   31494 allocs/op
BenchmarkAllocateAction_SmallCluster-4         	      10	 107545524 ns/op	 2180202 B/op	   31490 allocs/op
BenchmarkAllocateAction_SmallCluster-4         	      10	 107817794 ns/op	 2182776 B/op	   31488 allocs/op
BenchmarkAllocateAction_MediumCluster-4        	       8	 130225186 ns/op	10383987 B/op	  245792 allocs/op
BenchmarkAllocateAction_MediumCluster-4        	       8	 129568810 ns/op	10387620 B/op	  245795 allocs/op
BenchmarkAllocateAction_MediumCluster-4        	       8	 129969330 ns/op	10382514 B/op	  245780 allocs/op
BenchmarkAllocateAction_MediumCluster-4        	       8	 130424550 ns/op	10383323 B/op	  245773 allocs/op
BenchmarkAllocateAction_MediumCluster-4        	       8	 130375469 ns/op	10381928 B/op	  245771 allocs/op
BenchmarkAllocateAction_MediumCluster-4        	       8	 130311516 ns/op	10382476 B/op	  245743 allocs/op
BenchmarkAllocateAction_LargeCluster-4         	       6	 193583238 ns/op	32779146 B/op	 1007212 allocs/op
BenchmarkAllocateAction_LargeCluster-4         	       6	 190648104 ns/op	32776170 B/op	 1007200 allocs/op
BenchmarkAllocateAction_LargeCluster-4         	       6	 191418763 ns/op	32797722 B/op	 1007164 allocs/op
BenchmarkAllocateAction_LargeCluster-4         	       6	 193039553 ns/op	32797206 B/op	 1007193 allocs/op
BenchmarkAllocateAction_LargeCluster-4         	       6	 188344300 ns/op	32788264 B/op	 1007095 allocs/op
BenchmarkAllocateAction_LargeCluster-4         	       6	 191677291 ns/op	32798446 B/op	 1007203 allocs/op
BenchmarkReclaimAction_SmallCluster-4          	      10	 103025663 ns/op	  977000 B/op	    8934 allocs/op
BenchmarkReclaimAction_SmallCluster-4          	      10	 103556174 ns/op	  978450 B/op	    8937 allocs/op
BenchmarkReclaimAction_SmallCluster-4          	      10	 103329680 ns/op	  978442 B/op	    8937 allocs/op
BenchmarkReclaimAction_SmallCluster-4          	      10	 103314779 ns/op	  974240 B/op	    8935 allocs/op
BenchmarkReclaimAction_SmallCluster-4          	      10	 103237629 ns/op	  978380 B/op	    8937 allocs/op
BenchmarkReclaimAction_SmallCluster-4          	      10	 103809839 ns/op	  978294 B/op	    8937 allocs/op
BenchmarkReclaimAction_MediumCluster-4         	      10	 106718302 ns/op	 3258659 B/op	   28120 allocs/op
BenchmarkReclaimAction_MediumCluster-4         	      10	 107457306 ns/op	 3257070 B/op	   28120 allocs/op
BenchmarkReclaimAction_MediumCluster-4         	      10	 106279753 ns/op	 3256671 B/op	   28119 allocs/op
BenchmarkReclaimAction_MediumCluster-4         	      10	 106228724 ns/op	 3253082 B/op	   28119 allocs/op
BenchmarkReclaimAction_MediumCluster-4         	      10	 105928959 ns/op	 3257037 B/op	   28119 allocs/op
BenchmarkReclaimAction_MediumCluster-4         	      10	 106153341 ns/op	 3257424 B/op	   28120 allocs/op
BenchmarkPreemptAction_SmallCluster-4          	      10	 104620212 ns/op	 1411616 B/op	   15268 allocs/op
BenchmarkPreemptAction_SmallCluster-4          	      10	 104730509 ns/op	 1407852 B/op	   15268 allocs/op
BenchmarkPreemptAction_SmallCluster-4          	      10	 104376564 ns/op	 1408388 B/op	   15268 allocs/op
BenchmarkPreemptAction_SmallCluster-4          	      10	 104656688 ns/op	 1407924 B/op	   15268 allocs/op
BenchmarkPreemptAction_SmallCluster-4          	      10	 104516043 ns/op	 1404245 B/op	   15267 allocs/op
BenchmarkPreemptAction_SmallCluster-4          	      10	 104524979 ns/op	 1414447 B/op	   15268 allocs/op
BenchmarkPreemptAction_MediumCluster-4         	       9	 114330042 ns/op	 6220032 B/op	   55292 allocs/op
BenchmarkPreemptAction_MediumCluster-4         	       9	 113688319 ns/op	 6227963 B/op	   55291 allocs/op
BenchmarkPreemptAction_MediumCluster-4         	       9	 113966753 ns/op	 6219323 B/op	   55288 allocs/op
BenchmarkPreemptAction_MediumCluster-4         	       9	 113464395 ns/op	 6224607 B/op	   55295 allocs/op
BenchmarkPreemptAction_MediumCluster-4         	       9	 113438873 ns/op	 6220143 B/op	   55291 allocs/op
BenchmarkPreemptAction_MediumCluster-4         	       9	 114883056 ns/op	 6224018 B/op	   55292 allocs/op
BenchmarkConsolidationAction_SmallCluster-4    	       9	 121747622 ns/op	 8603392 B/op	  109664 allocs/op
BenchmarkConsolidationAction_SmallCluster-4    	       9	 121154533 ns/op	 8605959 B/op	  109695 allocs/op
BenchmarkConsolidationAction_SmallCluster-4    	       9	 121222070 ns/op	 8604226 B/op	  109686 allocs/op
BenchmarkConsolidationAction_SmallCluster-4    	       9	 121329600 ns/op	 8601117 B/op	  109656 allocs/op

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make deferred resize a scheduling event KAI considers when pre-empting and reclaiming

1 participant