Skip to content

perf(runtime): optimize version selector cache under cluster churn - #10946

Merged
ReubenBond merged 4 commits into
dotnet:mainfrom
ReubenBond:rb-10597-synchronize-selector-cache
Sep 2, 2026
Merged

ReubenBond merged 4 commits into
dotnet:mainfrom
ReubenBond:rb-10597-synchronize-selector-cache

Conversation

@ReubenBond

@ReubenBond ReubenBond commented Sep 1, 2026

Copy link
Copy Markdown
Member

PR #10597 established generation-consistent placement compatibility selection. In large clusters, the synchronized cache path and manifest index construction can dominate placement latency when membership changes frequently.

This follow-up preserves snapshot consistency while improving scaling:

  • captures one immutable manifest generation for each compatibility calculation
  • serves cache hits without a global monitor and coordinates refreshes per cache key
  • publishes selector and compatibility strategy changes through concurrency-safe registries
  • builds manifest silo indexes in linear time by relying on manifest key uniqueness
  • intersects and unions sorted silo sets without LINQ allocation chains, using an equality-consistent ordering for scoped IPv6 addresses
  • covers captured-generation behavior, reset races, IPv6 scope identity, and placement integration

BenchmarkDotNet ShortRun measurements on .NET 10 with 1,000 silos, 32 grain types, and 16 concurrent callers showed:

Scenario Before After Improvement
Concurrent cached selection 328.6 ns 69.4 ns 4.7x
Churn burst selection 12.09 ms 0.679 ms 17.8x
Manifest index rebuild 296.3 ms 8.7 ms 34x
Churn allocation 250.8 KB 108.4 KB 57% lower
Microsoft Reviewers: Open in CodeFlow

Copilot AI lite review requested due to automatic review settings September 1, 2026 22:10

Copilot AI 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.

Copilot review overview

🔵 Needs a closer look

It introduces substantial concurrency and caching behavior changes in a core runtime hot path which should receive final human review despite only minor issues found here.

Review tier: Lite
Findings: 2 Low severity

New issues introduced by this change (2)
Severity Finding
Low severity src/​Orleans.Runtime/​Versions/​CachedVersionSelectorManager.csGetSuitableSilos wraps its logic in while (true) but every path inside the loop returns, so the…
Low severity test/​Orleans.Core.Tests/​Manifest/​ClusterManifestProviderTests.cs — Test method name uses Ipv6 while other tests in this suite use IPv6 (e.g.,…
What changed in this PR

This PR is a performance-focused follow-up in Orleans runtime version selection/placement, aiming to keep selection snapshot-consistent under cluster churn while significantly reducing contention and allocations in the selector/manifests hot paths.

Changes:

  • Reworks CachedVersionSelectorManager to use per-key cache coordination (instead of a global lock) and to compute selections against an immutable captured manifest snapshot.
  • Updates GrainVersionManifest to expose captured snapshots and uses linear-time manifest indexing plus allocation-light sorted set union/intersection (with IPv6 scope-consistent ordering).
  • Makes selector/director registries concurrency-safe via ConcurrentDictionary + Volatile, and updates tests to cover snapshot consistency, reset races, and IPv6 scope behavior.
File Description
test/​Orleans.Core.Tests/​Runtime/​PlacementServiceTests.cs Updates test setup to match the new CachedVersionSelectorManager constructor (membership no longer injected).
test/​Orleans.Core.Tests/​Manifest/​ClusterManifestProviderTests.cs Replaces prior membership/manifest convergence retry test with new coverage for manifest snapshot capture consistency, reset race behavior, and IPv6 scope identity.
src/​Orleans.Runtime/​Versions/​Selector/​VersionDirectorManager.cs Switches selector registry to concurrency-safe storage and makes default selector updates thread-safe.
src/​Orleans.Runtime/​Versions/​Compatibility/​CompatibilityDirectorManager.cs Switches compatibility director registry to concurrency-safe storage and makes default director updates thread-safe.
src/​Orleans.Runtime/​Versions/​CachedVersionSelectorManager.cs Implements per-cache-key coordination + captured manifest snapshots; removes global-lock + membership-synchronized generation logic.
src/​Orleans.Core/​Manifest/​GrainVersionManifest.cs Adds captured snapshot API and optimized sorted set operations; ensures ordering distinguishes scoped IPv6 addresses consistently.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/Orleans.Runtime/Versions/CachedVersionSelectorManager.cs Outdated
Comment thread test/Orleans.Core.Tests/Manifest/ClusterManifestProviderTests.cs Outdated
Copilot AI review requested due to automatic review settings September 1, 2026 22:38

Copilot AI 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.

Copilot review overview

🔵 Needs a closer look

It changes core concurrency and ordering semantics in runtime placement/version-selection paths, which warrants final human validation despite added tests.

Review tier: Lite
Findings: None

Issues resolved since last review (2)
Severity Finding
Low severity test/​Orleans.Core.Tests/​Manifest/​ClusterManifestProviderTests.cs — Test method name uses Ipv6 while other tests in this suite use IPv6 (e.g.,… View resolved comment
Low severity src/​Orleans.Runtime/​Versions/​CachedVersionSelectorManager.csGetSuitableSilos wraps its logic in while (true) but every path inside the loop returns, so the… View resolved comment
Suppressed comments (2)

Previously missed (1) — in code that hasn't changed since the last review.

test/Orleans.Core.Tests/Manifest/ClusterManifestProviderTests.cs:190

  • membership is no longer passed into CreateCachedVersionSelectorManager, so the membership service setup and subsequent membership.Update(...) call in this test no longer affect the assertions and can be removed to avoid misleading future maintainers.

This issue also appears on line 213 of the same file.

test/Orleans.Core.Tests/Manifest/ClusterManifestProviderTests.cs:217

  • membership is created here but no longer used now that CachedVersionSelectorManager no longer depends on IClusterMembershipService. Removing it keeps the test focused on the manifest minor-version behavior being asserted.
        using var membership = new TestClusterMembershipService(CreateMembershipSnapshot(
            1,
            (localSilo, SiloStatus.Active),
            (remoteSilo, SiloStatus.Active)));
        var selectorManager = CreateCachedVersionSelectorManager(new GrainVersionManifest(clusterManifestProvider));

Copilot AI review requested due to automatic review settings September 1, 2026 22:44

Copilot AI 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.

Copilot review overview

🟡 Changes recommended

The per-key cache update in CachedVersionSelectorManager can allow an older manifest snapshot computation to overwrite a newer cached value, causing avoidable churn-time cache thrash and stale publication.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review tier: Lite
Findings: 1 Medium severity

New issues introduced by this change (1)
Severity Finding
Medium severity src/​Orleans.Runtime/​Versions/​CachedVersionSelectorManager.cs — Within the per-key lock, the cache write is gated only on cacheGeneration, so an in-flight…

Comment thread src/Orleans.Runtime/Versions/CachedVersionSelectorManager.cs
Copilot AI review requested due to automatic review settings September 1, 2026 23:01

Copilot AI 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.

Copilot review overview

🔵 Needs a closer look

It changes core runtime placement/versioning concurrency and caching behavior, so it warrants full human review with end-to-end CI validation and churn-focused runtime verification.

Review tier: Lite
Findings: None

Issues resolved since last review (1)
Severity Finding
Medium severity src/​Orleans.Runtime/​Versions/​CachedVersionSelectorManager.cs — Within the per-key lock, the cache write is gated only on cacheGeneration, so an in-flight… View resolved comment

Copilot AI 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.

Copilot review overview

🔵 Needs a closer look

It changes concurrency and caching behavior in the runtime placement/version-selection path, so it warrants final human review despite the added targeted tests.

Review tier: Lite
Findings: None

Copilot AI review requested due to automatic review settings September 2, 2026 03:33
@ReubenBond
ReubenBond force-pushed the rb-10597-synchronize-selector-cache branch from af4b135 to a2a4190 Compare September 2, 2026 03:33

Copilot AI 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.

Copilot review overview

🟢 Approval recommended

The concurrency and snapshot-consistency changes appear correct, are covered by targeted new tests, and I did not find any remaining call-site or correctness issues in the updated code paths.

Review tier: Lite
Findings: None

@ReubenBond
ReubenBond merged commit bf59244 into dotnet:main Sep 2, 2026
74 checks passed
@ReubenBond
ReubenBond deleted the rb-10597-synchronize-selector-cache branch September 2, 2026 15:08
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.

2 participants