Skip to content

perf(runtime): improve callback registry throughput - #10913

Open
ReubenBond wants to merge 9 commits into
dotnet:mainfrom
ReubenBond:rb-perf-runtime-route-callbacks-directly
Open

ReubenBond wants to merge 9 commits into
dotnet:mainfrom
ReubenBond:rb-perf-runtime-route-callbacks-directly

Conversation

@ReubenBond

@ReubenBond ReubenBond commented Aug 29, 2026

Copy link
Copy Markdown
Member

Silo callback tracking currently uses a ConcurrentDictionary<(GrainId, CorrelationId), CallbackData>, although the singleton MessageFactory already provides host-unique correlation IDs. The tuple key adds hashing, entry size, allocation, and contention to every silo-originated request.

This change uses a correlation-ID-only 128-stripe callback registry for the silo runtime. It preserves the external client dictionary path and adds the lifecycle guarantees needed by the runtime:

  • identity-checked cleanup prevents stale/ABA removal;
  • shutdown closes admission and waits for in-progress publication before sweeping callbacks;
  • timeout, cancellation, response, rejection, and shutdown races complete once;
  • pooled value snapshots support timeout and failure scans without retaining stale arrays;
  • exact count operations acquire every stripe in a consistent order.

Direct callback identity on Message was evaluated and removed. Matched local workloads found the registry fallback equal or faster, while the extra process-local field shifted CPU into response creation without an independent throughput benefit.

Exact-source validation used current main 137d9acc17830f15b13a4eb0058d6cee633cad5e, original PR head 88ed24754faf0b6e2a3fb06dff7f0dac706a0378, and final head bc5f49dc8. On a 32-logical-core AMD EPYC 7763 VM with .NET SDK 10.0.400 / runtime 10.0.11, a matched 25-second hosted-local C=100 trace measured:

Metric main final Change
Throughput 5.87M/s 6.74M/s +14.9%
P50 / P95 / P99 4.0 / 5.9 / 8.7 us 3.5 / 5.1 / 7.2 us -12.5% / -13.6% / -17.2%
Allocation 600 B/call 520 B/call -13.3%
CPU 4,592 ns/call 3,942 ns/call -14.2%
Monitor contentions 70,757 14,220 -79.9%

Hosted-local fixed-concurrency, async response-chain, exception-response, one-way, silo-to-silo, and external-client controls returned callback counts to zero. Remote and external-client throughput remained within run-to-run variance.

This PR supersedes the callback-registry implementation in #10062 and should not be merged alongside it. #10886 is independent and additive: the exact #10886 + #10913 stack improved hosted-local fixed C=16/100/500 by approximately 8–9% over #10886 alone, and AdaptivePing improved from 7.30M/s to 7.97M/s (+9.1%).

Microsoft Reviewers: Open in CodeFlow

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

Review tier: Lite
Findings: None

What changed in this PR

This PR optimizes Orleans runtime callback handling for local request/response flows by carrying a process-local callback identity on Message and completing callbacks directly, avoiding a shared callback-table lookup when the response remains in-process.

Changes:

  • Introduces a striped, correlation-id keyed callback table and a CallbackRegistry to support fast, contention-reduced callback lookup/removal with identity-checked cleanup.
  • Routes local responses through the Message.ResponseTarget fast-path while ensuring serialization omits the process-local target (remote/forwarded responses use fallback lookup).
  • Adds targeted tests for callback registry behavior, striped dictionary correctness/allocation behavior, and process-local serialization semantics.
File Description
test/​Orleans.Runtime.Tests/​StripedCallbackDictionaryTests.cs Adds correctness + allocation-focused tests for the striped callback dictionary.
test/​Orleans.Runtime.Tests/​CallbackRegistryTests.cs Adds behavioral tests for direct-target completion, fallback lookup, stale target handling, and close behavior.
test/​Orleans.Runtime.Tests/​CallbackDataTests.cs Updates test helper signature to align with identity-based unregister callback.
test/​Orleans.Core.Tests/​Serialization/​MessageSerializerTests.cs Verifies Message.ResponseTarget is process-local and not serialized across round-trips.
src/​Orleans.Runtime/​Core/​InsideRuntimeClient.cs Switches from ConcurrentDictionary callback tracking to CallbackRegistry and uses direct completion for local responses.
src/​Orleans.Runtime/​Core/​CallbackRegistry.cs Adds the registry which supports direct-target completion + striped fallback lookup/removal.
src/​Orleans.Core/​Runtime/​SharedCallbackData.cs Changes unregister callback signature to accept CallbackData (enabling identity-checked removal).
src/​Orleans.Core/​Runtime/​OutsideRuntimeClient.cs Updates unregister path to identity-checked removal while keeping the existing ConcurrentDictionary-based registry.
src/​Orleans.Core/​Runtime/​CallbackData.cs Updates unregister calls to pass this and adds TryDoCallback returning completion status.
src/​Orleans.Core/​Messaging/​StripedCallbackDictionary.cs Adds a 128-stripe, lock-based dictionary with snapshot enumeration and identity-checked removal.
src/​Orleans.Core/​Messaging/​MessageFactory.cs Propagates ResponseTarget onto responses created from a request.
src/​Orleans.Core/​Messaging/​Message.cs Adds a [NonSerialized] process-local ResponseTarget property on Message.

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

Copilot AI review requested due to automatic review settings August 29, 2026 06:45
@ReubenBond ReubenBond changed the title perf(runtime): route local callbacks directly perf(runtime): improve callback registry throughput Aug 29, 2026

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

Review tier: Lite
Findings: 1 Low severity

New issues introduced by this change (1)
Severity Finding
Low severity src/​Orleans.Runtime/​Core/​CallbackRegistry.csTryCompleteResponse returns false when the callback was found and removed but the callback had…

Comment thread src/Orleans.Runtime/Core/CallbackRegistry.cs
Copilot AI review requested due to automatic review settings August 29, 2026 10:15

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

Review tier: Lite
Findings: None

Issues resolved since last review (1)
Severity Finding
Low severity src/​Orleans.Runtime/​Core/​CallbackRegistry.csTryCompleteResponse returns false when the callback was found and removed but the callback had… View resolved comment

Copilot AI review requested due to automatic review settings August 31, 2026 21:54

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

Review tier: Lite
Findings: None

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 a highly concurrent, shutdown-sensitive runtime hot path (callback registration/completion/scans) and warrants final human review despite the added tests.

Review tier: Lite
Findings: None

Copilot AI review requested due to automatic review settings September 2, 2026 19:11

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 a core runtime concurrency mechanism in the request/response pipeline (callback lifecycle, shutdown, and races), which warrants final human review despite strong targeted test coverage.

Review tier: Lite
Findings: None

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 request/response callback lifecycle and shutdown/timeout race behavior in highly concurrent messaging paths, warranting final human verification.

Review tier: Lite
Findings: None

Copilot AI review requested due to automatic review settings September 2, 2026 22:47
@ReubenBond
ReubenBond force-pushed the rb-perf-runtime-route-callbacks-directly branch from 63ea5fa to 40ac09b Compare September 2, 2026 22:47

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 encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Code coverage

Metric Pull request Current main Variance
Lines 82.07% (112,056 / 136,545) 82.01% (111,893 / 136,444) +0.0587 pp
Branches 71.22% (32,196 / 45,204) 71.17% (32,155 / 45,178) +0.0498 pp

Report-only conclusion: improved.

The current-main baseline is commit 9222be9a19 and uses the same reviewed coverage matrix.

Coverage combines every CI test matrix job, including providers, CodeGen, .NET 8/10, Linux, Windows, and macOS, using canonical physical source and branch identities.

The comparison remains report-only while normal line and branch variance is calibrated.

Coverage details

Copilot AI review requested due to automatic review settings September 16, 2026 09:21
@ReubenBond
ReubenBond force-pushed the rb-perf-runtime-route-callbacks-directly branch from 40ac09b to 81ac18b Compare September 16, 2026 09:21

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

Update callback delegate consumers and the hosted-client registry test seam.

Get a fresh assessment by requesting another Copilot review.

Review tier: Lite
Findings: 2 High severity

Open (2)


public SharedCallbackData(
Action<Message> unregister,
Action<CallbackData> unregister,
private readonly ILoggerFactory loggerFactory;
private readonly SiloMessagingOptions messagingOptions;
private readonly ConcurrentDictionary<(GrainId, CorrelationId), CallbackData> callbacks;
private readonly CallbackRegistry callbacks;
Copilot AI review requested due to automatic review settings September 16, 2026 09:59

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

The broad, concurrency-sensitive callback lifecycle changes warrant final human review.

Review tier: Lite
Findings: 2 High severity

Open (2)

This branch has not been deployed

No deployments
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