Skip to content

perf(codegen): avoid runtime provider scanning - #10566

Merged
ReubenBond merged 1 commit into
dotnet:mainfrom
ReubenBond:rb-issue-10504-avoid-runtime-provider-scanning-with-gen-0ddaa6
Aug 12, 2026
Merged

ReubenBond merged 1 commit into
dotnet:mainfrom
ReubenBond:rb-issue-10504-avoid-runtime-provider-scanning-with-gen-0ddaa6

Conversation

@ReubenBond

@ReubenBond ReubenBond commented Aug 12, 2026 •

Copy link
Copy Markdown
Member

Problem

Configuration-driven client and silo providers still require eager assembly enumeration and reflection to find generated metadata, even when the current source generator has already resolved the complete provider set.

Solution

Emit a guarded module initializer whenever generated provider metadata exists and register that metadata in an AssemblyLoadContext-scoped runtime registry. Client and silo configuration now use the registry directly, refresh it on a miss for newly loaded generated assemblies, and only then initialize a shared one-time legacy reflection fallback.

The registry defines deterministic duplicate precedence, removes collectible-context registrations during unload, preserves generated-over-legacy precedence, and keeps custom type-manifest providers out of discovery.

Rationale

This keeps reflection and runtime assembly scanning off the successful generated path while retaining compatibility with assemblies built by older Orleans generators and preserving useful missing-provider diagnostics.

Fixes #10504

Microsoft Reviewers: Open in CodeFlow

Register generated provider metadata through module initializers and resolve it without assembly enumeration. Keep legacy binaries working through a lazy, one-time reflection fallback and isolate registry state by assembly load context.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI lite review requested due to automatic review settings August 12, 2026 17:32

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.

Pull request overview

This PR improves Orleans’ configuration-driven provider resolution by avoiding eager runtime assembly enumeration/reflection when provider metadata was already computed by the Orleans source generator. It introduces an AssemblyLoadContext-scoped registry populated via generated module initializers, and updates client/silo configuration to consult that registry first while retaining a lazy, cached legacy reflection fallback for older binaries.

Changes:

  • Added ProviderMetadataRegistry to store generator-emitted provider metadata per AssemblyLoadContext, with deterministic duplicate handling and unload cleanup for collectible contexts.
  • Updated ProviderRegistrationResolver to read from the registry on the fast path, refresh on misses (for newly loaded generated assemblies), and only then trigger a one-time legacy scan.
  • Extended unit tests to cover the registry fast-path behavior, fallback initialization semantics, deterministic duplicate resolution under concurrency, and collectible AssemblyLoadContext unload behavior; updated generator tests to validate module initializer emission.
Show a summary per file
File Description
test/Orleans.Core.Tests/ProviderRegistrationResolverTests.cs Adds tests for registry fast path, lazy fallback behavior, deterministic duplicates under concurrency, and collectible ALC unload behavior.
test/Orleans.CodeGenerator.Tests/OrleansSourceGeneratorTests.cs Verifies generated provider metadata emits a compilable module initializer which registers into the runtime registry.
test/Orleans.CodeGenerator.Tests/IncrementalCachingTests.cs Ensures incremental output changes include module initializer emission only when provider metadata appears.
src/Orleans.Serialization/Orleans.Serialization.csproj Grants InternalsVisibleTo access needed for Orleans.Core and test projects to call internal registry read APIs.
src/Orleans.Serialization/Configuration/ProviderMetadataRegistry.cs Introduces the ALC-scoped runtime registry and unload cleanup to avoid rooting collectible contexts.
src/Orleans.Runtime/Hosting/DefaultSiloServices.cs Switches silo provider resolution to use ProviderRegistrationResolver.Default registry-first path.
src/Orleans.Core/Core/ProviderRegistrationResolver.cs Refactors provider resolution to registry-first with miss refresh + one-time legacy reflection fallback.
src/Orleans.Core/Core/DefaultClientServices.cs Switches client provider resolution to use ProviderRegistrationResolver.Default registry-first path.
src/Orleans.CodeGenerator/OrleansSourceGenerator.cs Detects module-initializer support and passes the flag into metadata generation.
src/Orleans.CodeGenerator/MetadataSourceOutputGenerator.cs Plumbs module-initializer support into MetadataGenerator.
src/Orleans.CodeGenerator/MetadataGenerator.cs Emits a [ModuleInitializer] method to register generated provider metadata when supported and present.
src/api/Orleans.Serialization/Orleans.Serialization.cs Updates the public API surface to include ProviderMetadataRegistry.

Review details

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

  • Files reviewed: 12/12 changed files
  • Comments generated: 0
  • Review effort level: Lite

@ReubenBond
ReubenBond merged commit d3b2749 into dotnet:main Aug 12, 2026
73 checks passed
@ReubenBond
ReubenBond deleted the rb-issue-10504-avoid-runtime-provider-scanning-with-gen-0ddaa6 branch August 12, 2026 18:18
This was referenced Aug 28, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Avoid runtime provider scanning with generated module initializers

2 participants