Skip to content

fix(scheduler): don't leak pipeline-only fit errors onto live jobs - #1950

Closed
Thezone-1 wants to merge 2 commits into
kai-scheduler:mainfrom
Thezone-1:fix/1948-pipeline-only-fit-errors
Closed

fix(scheduler): don't leak pipeline-only fit errors onto live jobs#1950
Thezone-1 wants to merge 2 commits into
kai-scheduler:mainfrom
Thezone-1:fix/1948-pipeline-only-fit-errors

Conversation

@Thezone-1

Copy link
Copy Markdown
Contributor

Description

AllocateJob(..., isPipelineOnly=true) runs inside solver simulations (Reclaim, preempt, consolidation) that are rolled back with Statement.Rollback. Two paths recorded fit errors directly on the live session job during those simulations:

  • allocateTask wrote a task fit error when PrePredicateFn failed.
  • allocateTasksOnNodeSethandleFailedTaskAllocation wrote job fit errors on any task failure.

Statement.Rollback restores allocation state but not fit errors, so these simulation-only diagnostics leaked onto the pending job and could obscure the authoritative reason produced by the real Allocate pass. Someone inspecting a pending job's fit errors could then see a reason from a failed Reclaim simulation rather than why the scheduler actually couldn't place the job.

This change skips task and job fit-error writes when isPipelineOnly, mirroring the existing FittingNode(..., writeFittingDelta=!isPipelineOnly) behavior that already suppresses per-node fit deltas during simulation. The authoritative Allocate pass (isPipelineOnly=false) records fit errors exactly as before.

Related Issues

Fixes #1948

Checklist

  • Self-reviewed
  • Added/updated tests (if needed)
  • Updated documentation (if needed)
  • Added a changelog fragment

Breaking Changes

None.

Additional Notes

Includes the reproducer from the issue (TestSchedulingCyclePreservesAllocateFitErrors, authored by @enoodle): it runs a full action loop where Reclaim's pipeline-only simulation hits an injected pre-predicate failure, and asserts the job's task/job fit errors after all actions equal those produced by the initial Allocate.

Pipeline-only allocation runs inside solver simulations (e.g. Reclaim) that
are rolled back. allocateTask recorded pre-predicate fit errors, and
allocateTasksOnNodeSet recorded job fit errors, directly on the live session
job. Statement.Rollback does not restore fit errors, so simulation-only
diagnostics leaked onto pending jobs and masked the authoritative Allocate
reason.

Skip task and job fit-error writes when isPipelineOnly, mirroring the
existing FittingNode writeFittingDelta=!isPipelineOnly behavior.

Closes kai-scheduler#1948

Signed-off-by: Thezone-1 <somoprovobhattacharjee@gmail.com>
@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8ec08dfd-15e5-4d54-a8cb-9e7e65479d6e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown

Total coverage: 54.2% -> 53.4% (delta -0.80%)

Merging this branch will decrease overall coverage

Impacted Packages Coverage Δ 🤖
github.com/kai-scheduler/KAI-scheduler/pkg/scheduler/actions/common 24.18% (-0.20%) 👎
github.com/kai-scheduler/KAI-scheduler/pkg/scheduler/actions/integration_tests/reclaim 0.00% (ø)

Coverage by file

Changed files (no unit tests)

Changed File Coverage Δ Total Covered Missed 🤖
github.com/kai-scheduler/KAI-scheduler/pkg/scheduler/actions/common/allocate.go 0.00% (ø) 134 (+2) 0 134 (+2)

Please note that the "Total", "Covered", and "Missed" counts above refer to code statements instead of lines of code. The value in brackets refers to the test coverage of that file in the old version of the code.

Changed unit test files

  • github.com/kai-scheduler/KAI-scheduler/pkg/scheduler/actions/integration_tests/reclaim/reclaim_fit_errors_test.go

@github-actions

Copy link
Copy Markdown

📊 Performance Benchmark Results

Comparing PR (fix/1948-pipeline-only-fit-errors) vs main branch — click to expand
goos: linux
goarch: amd64
pkg: github.com/kai-scheduler/KAI-scheduler/pkg/scheduler/actions
cpu: AMD EPYC 7763 64-Core Processor                
                                    │ main-bench.txt │           pr-bench.txt            │
                                    │     sec/op     │   sec/op     vs base              │
AllocateAction_SmallCluster-4            108.5m ± 0%   108.4m ± 0%       ~ (p=0.310 n=6)
AllocateAction_MediumCluster-4           134.5m ± 0%   135.7m ± 1%  +0.86% (p=0.002 n=6)
AllocateAction_LargeCluster-4            195.4m ± 2%   197.7m ± 2%       ~ (p=0.093 n=6)
ReclaimAction_SmallCluster-4             103.4m ± 0%   103.6m ± 1%       ~ (p=0.589 n=6)
ReclaimAction_MediumCluster-4            107.1m ± 0%   106.9m ± 0%       ~ (p=0.485 n=6)
PreemptAction_SmallCluster-4             104.8m ± 0%   104.9m ± 0%       ~ (p=0.093 n=6)
PreemptAction_MediumCluster-4            117.8m ± 1%   119.5m ± 1%  +1.42% (p=0.009 n=6)
ConsolidationAction_SmallCluster-4       123.0m ± 1%   123.2m ± 0%       ~ (p=0.310 n=6)
ConsolidationAction_MediumCluster-4      270.0m ± 1%   270.6m ± 1%       ~ (p=0.240 n=6)
FullSchedulingCycle_SmallCluster-4       106.3m ± 0%   106.4m ± 0%       ~ (p=0.485 n=6)
FullSchedulingCycle_MediumCluster-4      120.1m ± 2%   120.5m ± 1%       ~ (p=0.240 n=6)
FullSchedulingCycle_LargeCluster-4       155.9m ± 1%   156.7m ± 1%       ~ (p=0.240 n=6)
ManyQueues_MediumCluster-4               138.0m ± 1%   140.4m ± 2%       ~ (p=0.065 n=6)
GangScheduling_MediumCluster-4           157.5m ± 2%   157.4m ± 1%       ~ (p=0.937 n=6)
geomean                                  133.3m        133.9m       +0.47%

                                    │ main-bench.txt │            pr-bench.txt            │
                                    │      B/op      │     B/op      vs base              │
AllocateAction_SmallCluster-4           2.074Mi ± 0%   2.074Mi ± 0%       ~ (p=0.818 n=6)
AllocateAction_MediumCluster-4          9.874Mi ± 0%   9.874Mi ± 0%       ~ (p=0.937 n=6)
AllocateAction_LargeCluster-4           31.19Mi ± 0%   31.19Mi ± 0%       ~ (p=0.310 n=6)
ReclaimAction_SmallCluster-4            950.5Ki ± 1%   951.7Ki ± 1%       ~ (p=0.394 n=6)
ReclaimAction_MediumCluster-4           3.090Mi ± 0%   3.088Mi ± 0%       ~ (p=0.093 n=6)
PreemptAction_SmallCluster-4            1.333Mi ± 0%   1.336Mi ± 0%       ~ (p=0.589 n=6)
PreemptAction_MediumCluster-4           5.901Mi ± 0%   5.901Mi ± 0%       ~ (p=0.699 n=6)
ConsolidationAction_SmallCluster-4      8.250Mi ± 0%   8.250Mi ± 0%       ~ (p=0.485 n=6)
ConsolidationAction_MediumCluster-4     68.84Mi ± 0%   68.85Mi ± 0%       ~ (p=0.818 n=6)
FullSchedulingCycle_SmallCluster-4      1.399Mi ± 1%   1.399Mi ± 1%       ~ (p=0.937 n=6)
FullSchedulingCycle_MediumCluster-4     6.117Mi ± 0%   6.118Mi ± 0%       ~ (p=0.240 n=6)
FullSchedulingCycle_LargeCluster-4      18.30Mi ± 0%   18.30Mi ± 0%       ~ (p=0.394 n=6)
ManyQueues_MediumCluster-4              13.11Mi ± 0%   13.11Mi ± 0%       ~ (p=0.394 n=6)
GangScheduling_MediumCluster-4          15.28Mi ± 0%   15.28Mi ± 0%       ~ (p=0.699 n=6)
geomean                                 6.531Mi        6.532Mi       +0.02%

                                    │ main-bench.txt │           pr-bench.txt            │
                                    │   allocs/op    │  allocs/op   vs base              │
AllocateAction_SmallCluster-4            31.48k ± 0%   31.48k ± 0%       ~ (p=0.777 n=6)
AllocateAction_MediumCluster-4           245.7k ± 0%   245.7k ± 0%       ~ (p=0.855 n=6)
AllocateAction_LargeCluster-4            1.007M ± 0%   1.007M ± 0%       ~ (p=0.167 n=6)
ReclaimAction_SmallCluster-4             8.927k ± 0%   8.927k ± 0%       ~ (p=1.000 n=6)
ReclaimAction_MediumCluster-4            28.07k ± 0%   28.07k ± 0%  -0.01% (p=0.011 n=6)
PreemptAction_SmallCluster-4             15.18k ± 0%   15.18k ± 0%       ~ (p=0.418 n=6)
PreemptAction_MediumCluster-4            54.94k ± 0%   54.94k ± 0%       ~ (p=0.810 n=6)
ConsolidationAction_SmallCluster-4       109.7k ± 0%   109.7k ± 0%       ~ (p=0.699 n=6)
ConsolidationAction_MediumCluster-4      1.021M ± 0%   1.021M ± 0%       ~ (p=0.818 n=6)
FullSchedulingCycle_SmallCluster-4       19.62k ± 0%   19.62k ± 0%       ~ (p=0.768 n=6)
FullSchedulingCycle_MediumCluster-4      136.2k ± 0%   136.2k ± 0%       ~ (p=0.667 n=6)
FullSchedulingCycle_LargeCluster-4       537.6k ± 0%   537.6k ± 0%       ~ (p=0.714 n=6)
ManyQueues_MediumCluster-4               274.0k ± 0%   274.0k ± 0%       ~ (p=0.818 n=6)
GangScheduling_MediumCluster-4           455.3k ± 0%   455.3k ± 0%       ~ (p=0.240 n=6)
geomean                                  108.8k        108.8k       -0.00%

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                                     139.3m ±  1%   140.2m ±  1%   +0.65% (p=0.009 n=6)
ReclaimLargeJobs_50Node-4                                     335.0m ±  7%   339.5m ±  4%        ~ (p=0.589 n=6)
ReclaimLargeJobs_100Node-4                                    684.6m ±  2%   707.1m ±  7%   +3.29% (p=0.002 n=6)
ReclaimLargeJobs_200Node-4                                     1.708 ±  3%    1.759 ±  2%   +2.99% (p=0.002 n=6)
ReclaimLargeJobs_500Node-4                                     7.780 ±  3%    7.888 ±  2%   +1.39% (p=0.041 n=6)
ReclaimLargeJobs_1000Node-4                                    33.78 ±  2%    33.12 ±  6%        ~ (p=0.394 n=6)
ReclaimManySingleGPUJobsFullCycle_10Node-4                    166.3m ±  1%   163.9m ±  2%        ~ (p=0.065 n=6)
ReclaimManySingleGPUJobsFullCycle_50Node-4                     1.105 ±  1%    1.101 ±  1%        ~ (p=0.132 n=6)
ReclaimManySingleGPUJobsFullCycle_100Node-4                    4.114 ±  5%    3.867 ±  0%   -6.00% (p=0.002 n=6)
ReclaimManySingleGPUJobsFullCycle_200Node-4                    18.43 ± 19%    15.73 ±  2%  -14.63% (p=0.002 n=6)
ReclaimManySingleGPUJobsFullCycle_500Node-4                    145.4 ± 27%    151.1 ± 27%        ~ (p=0.394 n=6)
ReclaimManySingleGPUJobsFullCycleWithMinRuntime_500Node-4      115.8 ± 12%    113.1 ± 42%        ~ (p=0.937 n=6)
geomean                                                        3.499          3.456         -1.22%

                                                          │ main-bench.txt │            pr-bench.txt            │
                                                          │      B/op      │     B/op      vs base              │
ReclaimLargeJobs_10Node-4                                     17.26Mi ± 1%   17.18Mi ± 1%  -0.49% (p=0.041 n=6)
ReclaimLargeJobs_50Node-4                                     92.06Mi ± 0%   91.83Mi ± 0%  -0.25% (p=0.002 n=6)
ReclaimLargeJobs_100Node-4                                    204.7Mi ± 0%   204.2Mi ± 0%  -0.22% (p=0.002 n=6)
ReclaimLargeJobs_200Node-4                                    487.2Mi ± 0%   486.3Mi ± 0%  -0.19% (p=0.002 n=6)
ReclaimLargeJobs_500Node-4                                    1.703Gi ± 0%   1.701Gi ± 0%  -0.12% (p=0.002 n=6)
ReclaimLargeJobs_1000Node-4                                   5.152Gi ± 0%   5.148Gi ± 0%  -0.08% (p=0.002 n=6)
ReclaimManySingleGPUJobsFullCycle_10Node-4                    15.66Mi ± 0%   15.64Mi ± 0%       ~ (p=0.180 n=6)
ReclaimManySingleGPUJobsFullCycle_50Node-4                    164.9Mi ± 0%   165.8Mi ± 0%  +0.56% (p=0.002 n=6)
ReclaimManySingleGPUJobsFullCycle_100Node-4                   550.7Mi ± 0%   554.9Mi ± 0%  +0.77% (p=0.002 n=6)
ReclaimManySingleGPUJobsFullCycle_200Node-4                   1.944Gi ± 0%   1.961Gi ± 0%  +0.92% (p=0.002 n=6)
ReclaimManySingleGPUJobsFullCycle_500Node-4                   12.92Gi ± 0%   13.12Gi ± 0%  +1.52% (p=0.002 n=6)
ReclaimManySingleGPUJobsFullCycleWithMinRuntime_500Node-4     12.92Gi ± 0%   13.12Gi ± 0%  +1.51% (p=0.002 n=6)
geomean                                                       547.3Mi        549.0Mi       +0.31%

                                                          │ main-bench.txt │           pr-bench.txt            │
                                                          │   allocs/op    │  allocs/op   vs base              │
ReclaimLargeJobs_10Node-4                                      246.5k ± 0%   245.2k ± 0%  -0.53% (p=0.002 n=6)
ReclaimLargeJobs_50Node-4                                      1.508M ± 0%   1.503M ± 0%  -0.34% (p=0.002 n=6)
ReclaimLargeJobs_100Node-4                                     3.799M ± 0%   3.789M ± 0%  -0.26% (p=0.002 n=6)
ReclaimLargeJobs_200Node-4                                     10.64M ± 0%   10.62M ± 0%  -0.19% (p=0.002 n=6)
ReclaimLargeJobs_500Node-4                                     45.91M ± 0%   45.87M ± 0%  -0.10% (p=0.002 n=6)
ReclaimLargeJobs_1000Node-4                                    160.2M ± 0%   160.1M ± 0%  -0.06% (p=0.002 n=6)
ReclaimManySingleGPUJobsFullCycle_10Node-4                     319.2k ± 0%   318.3k ± 0%  -0.28% (p=0.002 n=6)
ReclaimManySingleGPUJobsFullCycle_50Node-4                     4.707M ± 0%   4.705M ± 0%  -0.06% (p=0.002 n=6)
ReclaimManySingleGPUJobsFullCycle_100Node-4                    17.19M ± 0%   17.18M ± 0%  -0.02% (p=0.002 n=6)
ReclaimManySingleGPUJobsFullCycle_200Node-4                    65.46M ± 0%   65.46M ± 0%  -0.01% (p=0.002 n=6)
ReclaimManySingleGPUJobsFullCycle_500Node-4                    396.8M ± 0%   396.8M ± 0%  +0.00% (p=0.002 n=6)
ReclaimManySingleGPUJobsFullCycleWithMinRuntime_500Node-4      396.8M ± 0%   396.8M ± 0%  +0.00% (p=0.002 n=6)
geomean                                                        13.26M        13.24M       -0.15%

                                                          │ 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.12M ± 77%                        565.51M ± 6%  +1275.10% (p=0.002 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                     55.61M ± 57%                     577.97M ± 5%  +939.40% (p=0.002 n=6)

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       151.0m ± 1%   148.2m ± 3%  -1.87% (p=0.004 n=6)
ReclaimUnschedulableDistributedJob_50Node-4        3.659 ± 2%    3.667 ± 3%       ~ (p=0.937 n=6)
ReclaimUnschedulableDistributedJob_100Node-4       17.11 ± 1%    17.46 ± 2%  +2.02% (p=0.026 n=6)
ReclaimWithMissingPVCJobs-4                       2.740m ± 5%   2.672m ± 9%       ~ (p=0.310 n=6)
geomean                                           401.2m        399.0m       -0.54%

                                             │ main-bench.txt │            pr-bench.txt            │
                                             │      B/op      │     B/op      vs base              │
ReclaimUnschedulableDistributedJob_10Node-4      20.91Mi ± 3%   20.87Mi ± 3%       ~ (p=0.485 n=6)
ReclaimUnschedulableDistributedJob_50Node-4      1.151Gi ± 0%   1.149Gi ± 0%  -0.15% (p=0.002 n=6)
ReclaimUnschedulableDistributedJob_100Node-4     5.545Gi ± 0%   5.541Gi ± 0%  -0.07% (p=0.002 n=6)
ReclaimWithMissingPVCJobs-4                      9.086Ki ± 2%   9.086Ki ± 2%       ~ (p=1.000 n=6)
geomean                                          33.38Mi        33.35Mi       -0.11%

                                             │ main-bench.txt │           pr-bench.txt            │
                                             │   allocs/op    │  allocs/op   vs base              │
ReclaimUnschedulableDistributedJob_10Node-4       311.6k ± 3%   309.9k ± 3%  -0.53% (p=0.041 n=6)
ReclaimUnschedulableDistributedJob_50Node-4       27.79M ± 0%   27.75M ± 0%  -0.15% (p=0.002 n=6)
ReclaimUnschedulableDistributedJob_100Node-4      169.1M ± 0%   169.0M ± 0%  -0.05% (p=0.002 n=6)
ReclaimWithMissingPVCJobs-4                        170.0 ± 1%    170.0 ± 1%       ~ (p=1.000 n=6)
geomean                                           706.3k        705.0k       -0.19%

                                             │ 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) ¹
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) ¹
geomean                                            106.6          106.6       +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: AMD EPYC 7763 64-Core Processor                
BenchmarkAllocateAction_SmallCluster-4         	      10	 108403971 ns/op	 2182597 B/op	   31493 allocs/op
BenchmarkAllocateAction_SmallCluster-4         	      10	 108315381 ns/op	 2180134 B/op	   31474 allocs/op
BenchmarkAllocateAction_SmallCluster-4         	      10	 108412968 ns/op	 2169124 B/op	   31474 allocs/op
BenchmarkAllocateAction_SmallCluster-4         	      10	 108681602 ns/op	 2171850 B/op	   31477 allocs/op
BenchmarkAllocateAction_SmallCluster-4         	      10	 108375097 ns/op	 2172000 B/op	   31474 allocs/op
BenchmarkAllocateAction_SmallCluster-4         	      10	 108348315 ns/op	 2176496 B/op	   31482 allocs/op
BenchmarkAllocateAction_MediumCluster-4        	       8	 135267820 ns/op	10353623 B/op	  245696 allocs/op
BenchmarkAllocateAction_MediumCluster-4        	       8	 135462043 ns/op	10356428 B/op	  245765 allocs/op
BenchmarkAllocateAction_MediumCluster-4        	       8	 135924180 ns/op	10358544 B/op	  245720 allocs/op
BenchmarkAllocateAction_MediumCluster-4        	       8	 136075634 ns/op	10352134 B/op	  245701 allocs/op
BenchmarkAllocateAction_MediumCluster-4        	       8	 135310270 ns/op	10352183 B/op	  245715 allocs/op
BenchmarkAllocateAction_MediumCluster-4        	       8	 136867138 ns/op	10354130 B/op	  245707 allocs/op
BenchmarkAllocateAction_LargeCluster-4         	       6	 202200574 ns/op	32709810 B/op	 1007045 allocs/op
BenchmarkAllocateAction_LargeCluster-4         	       6	 197051441 ns/op	32722641 B/op	 1007067 allocs/op
BenchmarkAllocateAction_LargeCluster-4         	       6	 198411356 ns/op	32698656 B/op	 1007056 allocs/op
BenchmarkAllocateAction_LargeCluster-4         	       6	 201560199 ns/op	32748730 B/op	 1007085 allocs/op
BenchmarkAllocateAction_LargeCluster-4         	       6	 196397359 ns/op	32706220 B/op	 1007064 allocs/op
BenchmarkAllocateAction_LargeCluster-4         	       6	 196410518 ns/op	32708296 B/op	 1007018 allocs/op
BenchmarkReclaimAction_SmallCluster-4          	      10	 103515991 ns/op	  976754 B/op	    8925 allocs/op
BenchmarkReclaimAction_SmallCluster-4          	      10	 104100532 ns/op	  974511 B/op	    8929 allocs/op
BenchmarkReclaimAction_SmallCluster-4          	      10	 103364077 ns/op	  970533 B/op	    8926 allocs/op
BenchmarkReclaimAction_SmallCluster-4          	      10	 103566959 ns/op	  966615 B/op	    8925 allocs/op
BenchmarkReclaimAction_SmallCluster-4          	      10	 103540186 ns/op	  974500 B/op	    8927 allocs/op
BenchmarkReclaimAction_SmallCluster-4          	      10	 103611229 ns/op	  979122 B/op	    8927 allocs/op
BenchmarkReclaimAction_MediumCluster-4         	      10	 107050597 ns/op	 3236209 B/op	   28069 allocs/op
BenchmarkReclaimAction_MediumCluster-4         	      10	 107306073 ns/op	 3236742 B/op	   28069 allocs/op
BenchmarkReclaimAction_MediumCluster-4         	      10	 106964862 ns/op	 3240405 B/op	   28069 allocs/op
BenchmarkReclaimAction_MediumCluster-4         	      10	 106930975 ns/op	 3235864 B/op	   28067 allocs/op
BenchmarkReclaimAction_MediumCluster-4         	      10	 106567320 ns/op	 3239992 B/op	   28069 allocs/op
BenchmarkReclaimAction_MediumCluster-4         	      10	 106905184 ns/op	 3240028 B/op	   28068 allocs/op
BenchmarkPreemptAction_SmallCluster-4          	      10	 104781170 ns/op	 1400112 B/op	   15182 allocs/op
BenchmarkPreemptAction_SmallCluster-4          	      10	 104820070 ns/op	 1399866 B/op	   15183 allocs/op
BenchmarkPreemptAction_SmallCluster-4          	      10	 104995885 ns/op	 1403436 B/op	   15182 allocs/op
BenchmarkPreemptAction_SmallCluster-4          	      10	 104842866 ns/op	 1403765 B/op	   15184 allocs/op
BenchmarkPreemptAction_SmallCluster-4          	      10	 105267726 ns/op	 1402658 B/op	   15182 allocs/op
BenchmarkPreemptAction_SmallCluster-4          	      10	 104918588 ns/op	 1396071 B/op	   15182 allocs/op
BenchmarkPreemptAction_MediumCluster-4         	       9	 119410419 ns/op	 6191357 B/op	   54943 allocs/op
BenchmarkPreemptAction_MediumCluster-4         	       9	 118585487 ns/op	 6191513 B/op	   54943 allocs/op
BenchmarkPreemptAction_MediumCluster-4         	       9	 119603642 ns/op	 6183051 B/op	   54941 allocs/op
BenchmarkPreemptAction_MediumCluster-4         	       9	 119910151 ns/op	 6186923 B/op	   54940 allocs/op
BenchmarkPreemptAction_MediumCluster-4         	       9	 119825644 ns/op	 6187353 B/op	   54942 allocs/op
BenchmarkPreemptAction_MediumCluster-4         	       9	 118591139 ns/op	 6187262 B/op	   54942 allocs/op
BenchmarkConsolidationAction_SmallCluster-4    	       9	 123506747 ns/op	 8653216 B/op	  109704 allocs/op
BenchmarkConsolidationAction_SmallCluster-4    	       9	 123395240 ns/op	 8651288 B/op	  109697 allocs/op
BenchmarkConsolidationAction_SmallCluster-4    	       9	 123033742 ns/op	 8649766 B/op	  109684 allocs/op
BenchmarkConsolidationAction_SmallCluster-4    	       9	 122853773 ns/op	 8647456 B/op	  109668 allocs/op

Main branch:

goos: linux
goarch: amd64
pkg: github.com/kai-scheduler/KAI-scheduler/pkg/scheduler/actions
cpu: AMD EPYC 7763 64-Core Processor                
BenchmarkAllocateAction_SmallCluster-4         	      10	 108493877 ns/op	 2182159 B/op	   31491 allocs/op
BenchmarkAllocateAction_SmallCluster-4         	      10	 108380865 ns/op	 2164965 B/op	   31478 allocs/op
BenchmarkAllocateAction_SmallCluster-4         	      10	 108566971 ns/op	 2180878 B/op	   31480 allocs/op
BenchmarkAllocateAction_SmallCluster-4         	      10	 108361698 ns/op	 2172706 B/op	   31480 allocs/op
BenchmarkAllocateAction_SmallCluster-4         	      10	 108452617 ns/op	 2175781 B/op	   31475 allocs/op
BenchmarkAllocateAction_SmallCluster-4         	      10	 108589511 ns/op	 2165224 B/op	   31471 allocs/op
BenchmarkAllocateAction_MediumCluster-4        	       8	 134861569 ns/op	10352387 B/op	  245701 allocs/op
BenchmarkAllocateAction_MediumCluster-4        	       8	 134329946 ns/op	10354935 B/op	  245702 allocs/op
BenchmarkAllocateAction_MediumCluster-4        	       8	 134350485 ns/op	10357096 B/op	  245712 allocs/op
BenchmarkAllocateAction_MediumCluster-4        	       8	 134610798 ns/op	10354271 B/op	  245734 allocs/op
BenchmarkAllocateAction_MediumCluster-4        	       8	 135144427 ns/op	10351773 B/op	  245711 allocs/op
BenchmarkAllocateAction_MediumCluster-4        	       8	 134468729 ns/op	10352977 B/op	  245740 allocs/op
BenchmarkAllocateAction_LargeCluster-4         	       6	 196713764 ns/op	32703642 B/op	 1007009 allocs/op
BenchmarkAllocateAction_LargeCluster-4         	       6	 194016277 ns/op	32703861 B/op	 1007065 allocs/op
BenchmarkAllocateAction_LargeCluster-4         	       6	 196814450 ns/op	32701981 B/op	 1007100 allocs/op
BenchmarkAllocateAction_LargeCluster-4         	       6	 191508982 ns/op	32707705 B/op	 1007100 allocs/op
BenchmarkAllocateAction_LargeCluster-4         	       6	 197327298 ns/op	32731125 B/op	 1007120 allocs/op
BenchmarkAllocateAction_LargeCluster-4         	       6	 192310522 ns/op	32700828 B/op	 1007081 allocs/op
BenchmarkReclaimAction_SmallCluster-4          	      10	 103604585 ns/op	  972618 B/op	    8923 allocs/op
BenchmarkReclaimAction_SmallCluster-4          	      10	 103247291 ns/op	  973944 B/op	    8927 allocs/op
BenchmarkReclaimAction_SmallCluster-4          	      10	 103773586 ns/op	  970316 B/op	    8925 allocs/op
BenchmarkReclaimAction_SmallCluster-4          	      10	 103287041 ns/op	  967084 B/op	    8927 allocs/op
BenchmarkReclaimAction_SmallCluster-4          	      10	 103666339 ns/op	  974693 B/op	    8929 allocs/op
BenchmarkReclaimAction_SmallCluster-4          	      10	 103134337 ns/op	  974317 B/op	    8927 allocs/op
BenchmarkReclaimAction_MediumCluster-4         	      10	 107146657 ns/op	 3236262 B/op	   28069 allocs/op
BenchmarkReclaimAction_MediumCluster-4         	      10	 107219057 ns/op	 3240396 B/op	   28071 allocs/op
BenchmarkReclaimAction_MediumCluster-4         	      10	 107558524 ns/op	 3240288 B/op	   28071 allocs/op
BenchmarkReclaimAction_MediumCluster-4         	      10	 106966344 ns/op	 3241238 B/op	   28071 allocs/op
BenchmarkReclaimAction_MediumCluster-4         	      10	 106840298 ns/op	 3240211 B/op	   28071 allocs/op
BenchmarkReclaimAction_MediumCluster-4         	      10	 106913180 ns/op	 3240519 B/op	   28070 allocs/op
BenchmarkPreemptAction_SmallCluster-4          	      10	 104732562 ns/op	 1403850 B/op	   15184 allocs/op
BenchmarkPreemptAction_SmallCluster-4          	      10	 104914429 ns/op	 1392106 B/op	   15180 allocs/op
BenchmarkPreemptAction_SmallCluster-4          	      10	 104666274 ns/op	 1403696 B/op	   15182 allocs/op
BenchmarkPreemptAction_SmallCluster-4          	      10	 104603566 ns/op	 1396068 B/op	   15181 allocs/op
BenchmarkPreemptAction_SmallCluster-4          	      10	 104835607 ns/op	 1400156 B/op	   15183 allocs/op
BenchmarkPreemptAction_SmallCluster-4          	      10	 104821519 ns/op	 1395944 B/op	   15181 allocs/op
BenchmarkPreemptAction_MediumCluster-4         	       9	 118699969 ns/op	 6192056 B/op	   54946 allocs/op
BenchmarkPreemptAction_MediumCluster-4         	       9	 117635583 ns/op	 6190854 B/op	   54941 allocs/op
BenchmarkPreemptAction_MediumCluster-4         	       9	 118035372 ns/op	 6187178 B/op	   54942 allocs/op
BenchmarkPreemptAction_MediumCluster-4         	       9	 117529395 ns/op	 6187295 B/op	   54942 allocs/op
BenchmarkPreemptAction_MediumCluster-4         	       9	 117092912 ns/op	 6187478 B/op	   54943 allocs/op
BenchmarkPreemptAction_MediumCluster-4         	       9	 118538031 ns/op	 6187186 B/op	   54941 allocs/op
BenchmarkConsolidationAction_SmallCluster-4    	       9	 122936118 ns/op	 8650680 B/op	  109689 allocs/op
BenchmarkConsolidationAction_SmallCluster-4    	       9	 123484648 ns/op	 8650666 B/op	  109693 allocs/op
BenchmarkConsolidationAction_SmallCluster-4    	       9	 123185787 ns/op	 8650547 B/op	  109690 allocs/op
BenchmarkConsolidationAction_SmallCluster-4    	       9	 122878472 ns/op	 8648734 B/op	  109681 allocs/op

@Thezone-1

Copy link
Copy Markdown
Contributor Author

@
Hi @enoodle — friendly ping on this one. CI is green and it's mergeable whenever you get a chance.

Since you filed #1948, I wanted to flag the overlap with your own #1921 ("scope fit errors to authoritative allocation attempts") — that looks like it's tackling the same leak from the allocation-attempt side, whereas this PR guards the fit-error writes in allocate.go on !isPipelineOnly (mirroring FittingNode's writeFittingDelta) plus adds your reproducer as reclaim_fit_errors_test.go.

Happy to go whichever way makes sense: land this as the targeted fix, rebase it on top of #1921, or close it out if #1921 already covers the case. Just let me know what you'd prefer.
@

@enoodle

enoodle commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator

@Thezone-1 I haven't had time to look into this enough to form a solid opinion because this is a relatively minor issue. I hope to look into this next week.

@enoodle enoodle left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that the topology plugin would still add JobFitErrors to the job and other plugins can do that too. (see pkg/scheduler/plugins/topology/job_filtering.go:40 for example)

@Thezone-1

Copy link
Copy Markdown
Contributor Author

yeah you're right, and it's not only topology. job_filtering.go writes in 5 places and RecordVictimInvariantPrePredicateFailure in action_eligibility.go does too. FittingNode is fine since it already checks writeFittingDelta, but nothing stops the next plugin from adding one more.

so guarding call sites is a bit pointless, it only covers whatever I found today. the general version would be muting the writes on the PodGroupInfo for the duration of the pipeline-only attempt so it doesn't matter who writes them. I have that working locally but honestly I don't love it, it's a mutable flag on a shared object restored by defer, so an early return that skips the restore silently drops real fit errors, which is this bug backwards.

you said this one is fairly minor anyway, and your #1921 gets at the same leak from the allocation-attempt side without needing any of that. so I'm fine just closing this if #1921 covers it.

let me know which you'd rather, happy either way.

@Thezone-1

Copy link
Copy Markdown
Contributor Author

closing this one out. you were right that guarding the call sites in allocate.go only covers the writers I happened to find, and the general version (muting fit-error writes on the PodGroupInfo for the duration of the pipeline-only attempt) trades a narrow gap for a mutable flag on a shared object, which I don't think is a good trade for an issue you called minor.

#1921 gets at the same leak from the allocation-attempt side and doesn't need any of that, so it's the better home for this.

the reproducer test in here (TestSchedulingCyclePreservesAllocateFitErrors in pkg/scheduler/actions/integration_tests/reclaim/reclaim_fit_errors_test.go) is yours from #1948 and still passes on main. happy to send it as a standalone test-only PR if you want the coverage while #1921 lands. thanks for the review.

@Thezone-1 Thezone-1 closed this Aug 15, 2026
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.

Pipeline-only allocation leaks speculative fit errors

2 participants