Skip to content

refactor: Reuse TAS topology trees across scheduler snapshots - #13819

Merged
kubernetes-prow[bot] merged 1 commit into
kubernetes-sigs:mainfrom
akshay-pm:tas-static-tree
Aug 11, 2026
Merged

kubernetes-prow[bot] merged 1 commit into
kubernetes-sigs:mainfrom
akshay-pm:tas-static-tree

Conversation

@akshay-pm

@akshay-pm akshay-pm commented Aug 4, 2026 •

Copy link
Copy Markdown
Contributor

What type of PR is this?

/kind cleanup
/area tas

What this PR does / why we need it:

TAS snapshots previously rebuilt the complete topology tree for every scheduling cycle, including the domain hierarchy, node-to-domain mapping, and leaf capacities. Most of this data remains unchanged between cycles.

This PR:

  • Caches an immutable topology tree for each TAS flavor.
  • Reuses the tree while scheduling-relevant node data remains unchanged.
  • Keeps mutable scheduling state in each snapshot so concurrently created snapshots remain isolated.
  • Tracks semantic node changes to invalidate cached trees when labels, taints, or allocatable resources change.
  • Avoids invalidation for node updates that do not affect TAS scheduling.

Benchmark configuration:

  • 2,500 nodes
  • 15 TAS flavors
  • One non-TAS pod per node
Snapshot scenario CPU time Allocated bytes Allocations
Cached tree reused −71.74% −60.96% −64.50%
Tree invalidated every snapshot cycle +5.55% +10.54% +23.57%
Tree invalidated every 2 snapshot cycles −32.54% −25.05% −20.28%

pprof flame graphs
Before:

image

After:

image

Which issue(s) this PR fixes:

Part of #12580

Does this PR introduce a user-facing change?

TAS: Reduced CPU time and memory allocations for snapshot creation by reusing cached topology trees when scheduling-relevant Node data is unchanged. Controlled by the `TASCacheTopologyTree` feature gate, which is Beta and enabled by default.

Summary by CodeRabbit

  • Performance

    • Improved scheduling efficiency by reusing topology information across placement calculations.
    • Reduced unnecessary refreshes for heartbeat-only and unchanged node updates.
  • Scheduling

    • Improved balanced placement consistency with isolated scheduling state.
    • Enhanced handling of capacity, topology changes, pruning, fallback placement, and leader assignments.
  • Reliability

    • Improved consistency during concurrent topology updates.
    • Preserved the newest topology information during cache refreshes.
  • Testing

    • Expanded coverage for placement, topology changes, cache invalidation, and capacity handling.
    • Added benchmarks for topology reuse and assignment scenarios.

@kubernetes-prow kubernetes-prow Bot added kind/cleanup Categorizes issue or PR as related to cleaning up code, process, or technical debt. release-note Denotes a PR that will be considered when it comes time to generate release notes. area/tas Topology-Aware Scheduling needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. labels Aug 4, 2026
@kubernetes-prow

Copy link
Copy Markdown

Hi @akshay-pm. Thanks for your PR.

I'm waiting for a kubernetes-sigs member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work.

Tip

We noticed you've done this a few times! Consider joining the org to skip this step and gain /lgtm and other bot rights. We recommend asking approvers on your previous PRs to sponsor you.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@netlify

netlify Bot commented Aug 4, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for kubernetes-sigs-kueue ready!

Name Link
🔨 Latest commit e32a58c
🔍 Latest deploy log https://app.netlify.com/projects/kubernetes-sigs-kueue/deploys/6a76604471b7d80008725a3e
😎 Deploy Preview https://deploy-preview-13819--kubernetes-sigs-kueue.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@kubernetes-prow
kubernetes-prow Bot requested review from PBundyra and amy August 4, 2026 16:01
@kubernetes-prow kubernetes-prow Bot added cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. labels Aug 4, 2026
@coderabbitai

coderabbitai Bot commented Aug 4, 2026 •

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: dca3daf3-c713-4b08-9bd5-17bbae68bac1

📥 Commits

Reviewing files that changed from the base of the PR and between 7db3719 and e32a58c.

📒 Files selected for processing (2)
  • pkg/cache/scheduler/tas_cache_update_test.go
  • pkg/cache/scheduler/tas_flavor.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/cache/scheduler/tas_flavor.go

📝 Walkthrough

Walkthrough

TAS scheduling now reuses generation-aware topology trees and stores mutable placement state in individual snapshots. Balanced placement, capacity accounting, matching, cloning, pruning, tests, and benchmarks use snapshot-backed state.

Changes

TAS snapshot reuse and placement state

Layer / File(s) Summary
Generation tracking and cached topology trees
pkg/cache/scheduler/tas_nodes_cache.go, pkg/cache/scheduler/tas_topology_tree.go, pkg/cache/scheduler/tas_flavor.go, pkg/cache/scheduler/*_test.go
The node cache tracks scheduling-relevant generations. TAS flavor caches reuse or rebuild topology trees by generation.
Shared topology and snapshot-owned state
pkg/cache/scheduler/tas_flavor_snapshot.go
Topology data is shared across snapshots. Domain, leaf, candidate, capacity, and assignment state is snapshot-owned.
Snapshot-aware balanced placement
pkg/cache/scheduler/tas_balanced_placement.go, pkg/cache/scheduler/tas_balanced_placement_test.go
Balanced assignment, comparisons, cloning, clearing, pruning, and threshold calculations use snapshot state.
Snapshot migration and validation coverage
pkg/cache/scheduler/tas_flavor_snapshot_test.go, pkg/cache/scheduler/tas_flavor_snapshot_bench_test.go, pkg/cache/scheduler/tas_cache_test.go, pkg/cache/scheduler/snapshot.go
Tests and benchmarks use topology-backed snapshots. Coverage includes reuse, isolation, invalidation, concurrent assignment, and worker or leader assignments.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant TASNodesCache
  participant TASFlavorCache
  participant topologyTree
  participant TASFlavorSnapshot
  participant BalancedPlacement
  TASNodesCache->>TASFlavorCache: synchronize nodes and generation
  TASFlavorCache->>topologyTree: reuse or rebuild topology tree
  TASFlavorCache->>TASFlavorSnapshot: create isolated snapshot state
  TASFlavorSnapshot->>BalancedPlacement: provide domain and capacity state
  BalancedPlacement->>TASFlavorSnapshot: update assignment and pruning state
Loading

Possibly related issues

Suggested reviewers: amy, pbundyra

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.89% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: reusing TAS topology trees across scheduler snapshots.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ 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.

@mimowo

mimowo commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

/ok-to-test

@kubernetes-prow kubernetes-prow Bot added ok-to-test Indicates a non-member PR verified by an org member that is safe to test. and removed needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. labels Aug 4, 2026
@mimowo

mimowo commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Cc @j-skiba
Ptal

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (5)
pkg/cache/scheduler/tas_flavor_snapshot_bench_test.go (2)

224-226: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Replace the length-inequality proxy assertion.

The check fails when len(snapshot.state) equals len(snapshot.domains). It infers "state was cloned" from a length difference. That inference depends on an implementation detail of the cloning path, not on a stated invariant. A future change that clones state without changing its length would make this benchmark fail with a message that does not describe the real problem.

Assert the property directly, or drop the check and rely on the placement result.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/cache/scheduler/tas_flavor_snapshot_bench_test.go` around lines 224 -
226, Remove the length-based clone assertion in the balanced placement
preflight, since len(snapshot.state) versus len(snapshot.domains) does not
directly verify cloning. Either assert the actual cloned-state property using an
exposed identity/content invariant, or rely solely on the placement result; do
not retain this proxy check or its misleading failure message.

228-232: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Drop the redundant b.ResetTimer()/b.StopTimer() calls around b.Loop().

b.Loop() already resets the timer before the first iteration and stops it when the loop ends, so these calls add no timing benefit. runBenchmarkTASFlavorSnapshot uses b.Loop() without them, so removing them keeps both benchmarks consistent.

♻️ Proposed cleanup
-		b.ResetTimer()
 		for b.Loop() {
 			result = snapshot.FindTopologyAssignmentsForFlavor(b.Context(), requests)
 		}
-		b.StopTimer()
 		if failure := result.Failure(); failure != nil {
 			b.Fatalf("repeated balanced placement failed: %s", failure.Reason)
 		}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/cache/scheduler/tas_flavor_snapshot_bench_test.go` around lines 228 -
232, Remove the redundant b.ResetTimer() and b.StopTimer() calls surrounding the
b.Loop() in the benchmark using snapshot.FindTopologyAssignmentsForFlavor. Keep
the b.Loop() iteration and result assignment unchanged, matching
runBenchmarkTASFlavorSnapshot.
pkg/cache/scheduler/tas_flavor_snapshot_test.go (1)

43-52: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Document the difference between addDomainsWithState and addDomainWithState.

This package now has two similarly named helpers with different aliasing behavior. addDomainsWithState copies spec.domain into a new value, so a shared fixture can be registered in several snapshots safely. addDomainWithState in pkg/cache/scheduler/tas_balanced_placement_test.go mutates the caller's *domain in place and returns the same pointer, so a shared fixture would be aliased across snapshots.

Add a short doc comment on each helper that states the aliasing behavior. That prevents a future test from passing a shared *domain to addDomainWithState and getting cross-test state corruption.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/cache/scheduler/tas_flavor_snapshot_test.go` around lines 43 - 52, Add
short doc comments to both addDomainsWithState and addDomainWithState describing
their distinct aliasing behavior: addDomainsWithState copies each domain value
before registering it, while addDomainWithState mutates and returns the caller’s
existing pointer. Keep the comments focused on preventing shared-fixture
aliasing across snapshots.
pkg/cache/scheduler/tas_flavor_test.go (1)

142-156: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider covering the equal-generation case in storeTree.

storeTree replaces the cached tree when tree.generation >= c.tree.generation, so a second tree at the same generation wins. No test pins that branch. If someone later changes >= to >, no test fails, and the tie behavior changes silently.

♻️ Proposed additional assertion
 	if got := cache.cachedTree(); got != newer {
 		t.Fatal("storeTree replaced the cached tree with an older tree")
 	}
+
+	sameGeneration := &topologyTree{generation: 2}
+	if got := cache.storeTree(sameGeneration); got != sameGeneration {
+		t.Fatal("storeTree did not adopt a tree at the same generation")
+	}
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/cache/scheduler/tas_flavor_test.go` around lines 142 - 156, Extend
TestStoreTreeReturnsNewest to store a second topologyTree with the same
generation as the cached tree and assert that storeTree returns and cachedTree
expose this newer equal-generation tree, pinning the >= replacement behavior
without changing the existing older-generation assertions.
pkg/cache/scheduler/tas_flavor_snapshot.go (1)

1944-1949: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Document the lifetime rule for cloned domains.

The truncation makes every *domain produced by shallowCloneWithState invalid, because those clones carry idx >= len(s.domains). After this reslice, stateOf(staleClone) either panics or, once new clones are appended, aliases an unrelated clone's state.

The invariant holds today: fillInCounts runs at the start of findTopologyAssignment, all clones are created later in the same call, and buildTopologyAssignmentForLevels copies values out instead of returning *domain. The rule is enforced only by convention, so state it here.

♻️ Proposed comment addition
 	// cleanup the state in case some remaining values are present from computing
 	// assignments for previous PodSets. Truncating to discard the state
 	// slots of domain copies made for the previous PodSet.
+	//
+	// This invalidates every *domain returned by shallowCloneWithState, whose
+	// idx points past len(s.domains). Cloned domains must not outlive the
+	// findTopologyAssignment call that created them.
 	s.state = s.state[:len(s.domains)]
 	clear(s.state)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/cache/scheduler/tas_flavor_snapshot.go` around lines 1944 - 1949, Add a
concise comment beside the state truncation in TASFlavorSnapshot.fillInCounts
documenting that shallowCloneWithState results must not outlive this reset
because their state indices are invalidated or may alias later clones. State
that fillInCounts runs before creating clones and that downstream topology
assignment copies values rather than returning clone pointers, preserving this
lifetime convention.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/cache/scheduler/tas_flavor_snapshot.go`:
- Around line 456-462: Update the comment above addNonTASUsage to state that
domainID comes from the topologyTree’s nodeToDomain map, while leaves is
populated from the same node set by newTopologyTree, guaranteeing the
corresponding leaf exists. Remove the outdated explanation tying the guarantee
to nodes having TAS pods; leave the dereference and surrounding logic unchanged.

---

Nitpick comments:
In `@pkg/cache/scheduler/tas_flavor_snapshot_bench_test.go`:
- Around line 224-226: Remove the length-based clone assertion in the balanced
placement preflight, since len(snapshot.state) versus len(snapshot.domains) does
not directly verify cloning. Either assert the actual cloned-state property
using an exposed identity/content invariant, or rely solely on the placement
result; do not retain this proxy check or its misleading failure message.
- Around line 228-232: Remove the redundant b.ResetTimer() and b.StopTimer()
calls surrounding the b.Loop() in the benchmark using
snapshot.FindTopologyAssignmentsForFlavor. Keep the b.Loop() iteration and
result assignment unchanged, matching runBenchmarkTASFlavorSnapshot.

In `@pkg/cache/scheduler/tas_flavor_snapshot_test.go`:
- Around line 43-52: Add short doc comments to both addDomainsWithState and
addDomainWithState describing their distinct aliasing behavior:
addDomainsWithState copies each domain value before registering it, while
addDomainWithState mutates and returns the caller’s existing pointer. Keep the
comments focused on preventing shared-fixture aliasing across snapshots.

In `@pkg/cache/scheduler/tas_flavor_snapshot.go`:
- Around line 1944-1949: Add a concise comment beside the state truncation in
TASFlavorSnapshot.fillInCounts documenting that shallowCloneWithState results
must not outlive this reset because their state indices are invalidated or may
alias later clones. State that fillInCounts runs before creating clones and that
downstream topology assignment copies values rather than returning clone
pointers, preserving this lifetime convention.

In `@pkg/cache/scheduler/tas_flavor_test.go`:
- Around line 142-156: Extend TestStoreTreeReturnsNewest to store a second
topologyTree with the same generation as the cached tree and assert that
storeTree returns and cachedTree expose this newer equal-generation tree,
pinning the >= replacement behavior without changing the existing
older-generation assertions.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 3eb30ae1-dba1-4982-ae63-b7f585ad13f2

📥 Commits

Reviewing files that changed from the base of the PR and between ae0a478 and 20b0d35.

📒 Files selected for processing (12)
  • pkg/cache/scheduler/snapshot.go
  • pkg/cache/scheduler/tas_balanced_placement.go
  • pkg/cache/scheduler/tas_balanced_placement_test.go
  • pkg/cache/scheduler/tas_cache_test.go
  • pkg/cache/scheduler/tas_flavor.go
  • pkg/cache/scheduler/tas_flavor_snapshot.go
  • pkg/cache/scheduler/tas_flavor_snapshot_bench_test.go
  • pkg/cache/scheduler/tas_flavor_snapshot_test.go
  • pkg/cache/scheduler/tas_flavor_snapshot_tree_test.go
  • pkg/cache/scheduler/tas_flavor_test.go
  • pkg/cache/scheduler/tas_nodes_cache.go
  • pkg/cache/scheduler/tas_nodes_cache_test.go

Comment thread pkg/cache/scheduler/tas_flavor_snapshot.go
@mimowo

mimowo commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

https://prow.k8s.io/view/gs/kubernetes-ci-logs/pr-logs/pull/kubernetes-sigs_kueue/13819/pull-kueue-test-integration-shard-2-main/2084671642113413120

It looks unrelated because this is non TAS, but I haven't seen this before, not sure

@mimowo

mimowo commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

https://prow.k8s.io/view/gs/kubernetes-ci-logs/pr-logs/pull/kubernetes-sigs_kueue/13819/pull-kueue-test-integration-shard-2-main/2084671642113413120

@coderabbitai please open a flake issue remembering to add the kind/flake label and the link to the failed log

@mimowo

mimowo commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

/test pull-kueue-test-integration-shard-2-main

@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="kubernetes-sigs/kueue"
log_url="https://prow.k8s.io/view/gs/kubernetes-ci-logs/pr-logs/pull/kubernetes-sigs_kueue/13819/pull-kueue-test-integration-shard-2-main/2084671642113413120"

printf '%s\n' '--- Prow result ---'
curl -fsSL "$log_url" | sed -n '1,220p'

printf '%s\n' '--- Required label ---'
gh label list --repo "$repo" --search "kind/flake" --limit 20

Length of output: 8291


🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="kubernetes-sigs/kueue"
log_url="https://prow.k8s.io/view/gs/kubernetes-ci-logs/pr-logs/pull/kubernetes-sigs_kueue/13819/pull-kueue-test-integration-shard-2-main/2084671642113413120"
artifact_url="https://storage.googleapis.com/kubernetes-ci-logs/pr-logs/pull/kubernetes-sigs_kueue/13819/pull-kueue-test-integration-shard-2-main/2084671642113413120/build-log.txt"

printf '%s\n' '--- Build-log failure context ---'
curl -fsSL "$artifact_url" |
  grep -nE -i '(^FAIL|--- FAIL:|error:|panic:|timed out|timeout|failed)' |
  tail -80 || true

printf '%s\n' '--- Existing issues with this log ---'
gh issue list \
  --repo "$repo" \
  --state all \
  --search "\"$log_url\" in:body" \
  --limit 20 \
  --json number,title,url,state

Length of output: 20224


🏁 Script executed:

#!/bin/bash
set -euo pipefail

artifact_url="https://storage.googleapis.com/kubernetes-ci-logs/pr-logs/pull/kubernetes-sigs_kueue/13819/pull-kueue-test-integration-shard-2-main/2084671642113413120/build-log.txt"

curl -fsSL "$artifact_url" | sed -n '17480,17635p'

Length of output: 23160


🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="kubernetes-sigs/kueue"
log_url="https://prow.k8s.io/view/gs/kubernetes-ci-logs/pr-logs/pull/kubernetes-sigs_kueue/13819/pull-kueue-test-integration-shard-2-main/2084671642113413120"
pr_url="https://github.com/kubernetes-sigs/kueue/pull/13819"

body=$(cat <<EOF
## Summary

The \`pull-kueue-test-integration-shard-2-main\` Prow job failed with one failing integration test. The PR changes TAS snapshot caching, but the failed suite is the non-TAS core controller integration suite.

## Failed test

\`\`\`
Queue controller [It] Should update conditions when clusterQueues that its localQueue references are updated
\`\`\`

- Suite: \`core\` (\`test/integration/singlecluster/controller/core\`)
- Source location: \`test/integration/singlecluster/controller/core/localqueue_controller_test.go:183\`
- Result: 72 passed, 1 failed

## Failed log

${log_url}

## Context

- Reported from PR `#13819`: ${pr_url}
- Requested by: `@mimowo`

## Acceptance criteria

- Reproduce or determine the source of the intermittent failure.
- Stabilize the test or the tested controller behavior.
- Verify repeated execution of the affected integration suite does not reproduce the failure.
EOF
)

issue_url=$(gh issue create \
  --repo "$repo" \
  --title "[Flake] LocalQueue conditions update integration test" \
  --body "$body" \
  --label "kind/flake" \
  --assignee "mimowo")

printf 'Created issue: %s\n' "$issue_url"

Length of output: 1646


@mimowo Created #13821 for the flaky integration test.

The issue has the kind/flake label, includes the failed-log link, and is assigned to you.

You are interacting with an AI system.

@mimowo

mimowo commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

/test pull-kueue-test-integration-shard-2-main

@kubernetes-prow kubernetes-prow Bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Aug 5, 2026
@j-skiba

j-skiba commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

/assign


// domainState is the per-snapshot mutable state of a domain during the
// assignment algorithm, addressed by domain.idx.
type domainState struct {

@j-skiba j-skiba Aug 5, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

maybe nit:

IMO it gets a little overwhelming to use "state" everywhere. I think the *.state*. fields in domainState could be named more expressively in the first place like podCount/sliceCount maybe. It feels more intuitive to me.

It could be a separate PR.

Because now we have a few "state" structs that refer to state in different aspects. domainState has possible pod count states while leafState has resource capacity.

Or maybe we could at least rename leafState to leafCapacity or something similar.

Also naming here is a little inconsistent:

type TASFlavorSnapshot struct {
	log logr.Logger

	// topologyName indicates the name of the topology specified in the
	// ResourceFlavor spec.topologyName field.
	topologyName kueue.TopologyReference

	// topologyTree is the static topology structure, shared with the other
	// snapshots of the flavor. It must not be mutated.
	*topologyTree

	// state holds the per-snapshot mutable domain state, indexed by
	// domain.idx.
	state []domainState

	// leafStates holds the per-snapshot mutable leaf state, indexed by
	// leafDomain.leafIdx.
	leafStates []leafState

state and leafStates

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Agreed. I'll raise a separate PR for this. The rename comes to roughly 500 lines of mechanical changes across 6 files, which could dominate the diff and make it easier to miss any core issues.


// domain holds the static information about placement of a topology
// domain in the hierarchy of topology domains.
// Its per-snapshot mutable state lives in TASFlavorSnapshot.state,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm wondering if splitting this file would be good decision now.

We have 2 topics here:

  • immutable, read-only structures
  • per-cycle mutable strcutures

it looks like a candidate for splitting. Tree already has separate test file so it sounds natural to me.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done. Added a new file tas_topology_tree.go with all the static parts and renamed the test file to tas_topology_tree_test.go match.

Comment on lines +107 to +108
FreeCapacity map[corev1.ResourceName]int64
TASUsage map[corev1.ResourceName]int64

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think we could use Requests from pkg/resources/interface.go here and when calling cmp.Diff pass cmp.Comparer(resources.Equal).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks for pointing it out. MIssed resources.Equal. Switched to resources.Requests and dropped requestsToMap entirely.

Comment on lines +57 to +66
func requestsToMap(r resources.Requests) map[corev1.ResourceName]int64 {
if r == nil {
return nil
}
result := make(map[corev1.ResourceName]int64, r.Len())
r.ForEach(func(name corev1.ResourceName, value int64) {
result[name] = value
})
return result
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done. Removed.

for b.Loop() {
result = snapshot.FindTopologyAssignmentsForFlavor(b.Context(), requests)
}
b.StopTimer()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think we don't need to call that, b.Loop() should stop timer internally - https://cs.opensource.google/go/go/+/refs/tags/go1.26.5:src/testing/benchmark.go;drc=fb5156a0981c2b89a118695138194e1af162ac8e;l=482

Suggested change
b.StopTimer()

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes it was not required. Removed.

Comment on lines +332 to +335
domainState := s.stateOf(d)
domainState.stateWithLeader = int32(0)
domainState.sliceStateWithLeader = int32(0)
domainState.leaderState = int32(0)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

do we need these int32 wraps?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

No I don't think its required. Removed.

Comment on lines +162 to +164
cycle := 0
for b.Loop() {
switch {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We could reset timer here and not include setup procedures in the measurement, the same way we do in the new benchmark

Suggested change
cycle := 0
for b.Loop() {
switch {
cycle := 0
b.ResetTimer()
for b.Loop() {
switch {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@mimowo

mimowo commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

cc @apullo777 would you like to give it a pass here?

@apullo777

Copy link
Copy Markdown
Member

/assign

@kubernetes-prow

Copy link
Copy Markdown

LGTM label has been added.

DetailsGit tree hash: 8586c429eb028695a9c83b1160be12ad613ad459

@mimowo mimowo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

/lgtm
/approve

Thank you for this excellent effort 👍 It not only improves the performance but also the readability of code with the tas_topology_tree extracted.

Thank you also for @j-skiba raising the idea and @apullo777 for your review 🥇

@kubernetes-prow

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: akshay-pm, mimowo

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@kubernetes-prow kubernetes-prow Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Aug 11, 2026
@kubernetes-prow
kubernetes-prow Bot merged commit fc9f60c into kubernetes-sigs:main Aug 11, 2026
56 checks passed
@kubernetes-prow kubernetes-prow Bot added this to the v0.20 milestone Aug 11, 2026
@mimowo mimowo mentioned this pull request Aug 11, 2026
3 tasks
kubernetes-prow Bot pushed a commit that referenced this pull request Aug 20, 2026
…cross scheduler snapshots (#14644)

* Reuse TAS topology trees across scheduler snapshots

* Add TASCacheTopologyTree Feature Gate

Signed-off-by: Yuki Iwai <yuki.iwai.tz@gmail.com>

* Fix 2 formatting errors

Signed-off-by: Yuki Iwai <yuki.iwai.tz@gmail.com>

---------

Signed-off-by: Yuki Iwai <yuki.iwai.tz@gmail.com>
Co-authored-by: Akshay PM <akshaypm.mail@gmail.com>
kubernetes-prow Bot pushed a commit that referenced this pull request Aug 20, 2026
…cross scheduler snapshots (#14639)

* Reuse TAS topology trees across scheduler snapshots

* Add TASCacheTopologyTree Feature Gate

Signed-off-by: Yuki Iwai <yuki.iwai.tz@gmail.com>

* TASCacheTopologyTree FG phase is changed

Signed-off-by: Yuki Iwai <yuki.iwai.tz@gmail.com>

---------

Signed-off-by: Yuki Iwai <yuki.iwai.tz@gmail.com>
Co-authored-by: Akshay PM <akshaypm.mail@gmail.com>
@tenzen-y

Copy link
Copy Markdown
Member

/kind feature
/remove-kind cleanup

@kubernetes-prow kubernetes-prow Bot added kind/feature Categorizes issue or PR as related to a new feature. and removed kind/cleanup Categorizes issue or PR as related to cleaning up code, process, or technical debt. labels Aug 20, 2026
@tenzen-y

Copy link
Copy Markdown
Member

/release-note-edit

TAS: Reduced CPU time and memory allocations for snapshot creation by reusing cached topology trees when scheduling-relevant Node data is unchanged.

New behaviors are guarded by the TASCacheTopologyTree feature gate, enabled by default.

@tenzen-y

Copy link
Copy Markdown
Member

/release-note-edit

TAS: Reduced CPU time and memory allocations for snapshot creation by reusing cached topology trees when scheduling-relevant Node data is unchanged. Controlled by the `TASCacheTopologyTree` feature gate, which is Beta and enabled by default.

@j-skiba j-skiba mentioned this pull request Oct 16, 2026
3 tasks done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. area/tas Topology-Aware Scheduling cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. kind/feature Categorizes issue or PR as related to a new feature. lgtm "Looks good to me", indicates that a PR is ready to be merged. ok-to-test Indicates a non-member PR verified by an org member that is safe to test. release-note Denotes a PR that will be considered when it comes time to generate release notes. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants