Skip to content

perf(codegen): generate provider metadata at build time - #10493

Merged
ReubenBond merged 8 commits into
dotnet:mainfrom
ReubenBond:rb-fix-pr-9731
Aug 12, 2026
Merged

ReubenBond merged 8 commits into
dotnet:mainfrom
ReubenBond:rb-fix-pr-9731

Conversation

@ReubenBond

@ReubenBond ReubenBond commented Aug 11, 2026 •

Copy link
Copy Markdown
Member

Problem

Configuration-driven providers are declared with RegisterProviderAttribute. Resolving them entirely from those attributes at runtime requires assembly enumeration and reflection, and the original implementation in #9731 predates the incremental source-generator architecture.

Solution

  • Collect provider registrations declared by each assembly in the incremental source-generator model while preserving structural equality and deterministic ordering for caching.
  • Emit a lightweight IProviderMetadataProvider implementation only when complete provider metadata can be represented safely in generated C#.
  • Resolve client and silo providers through a shared runtime resolver without executing the full generated serialization manifest.
  • Avoid activating custom type-manifest providers outside dependency injection and preserve generated provider constructors for trimming/AOT.
  • Preserve compatibility with assemblies built by older generators, and assemblies containing alias-only or file-local provider types, using a narrowly scoped RegisterProviderAttribute fallback.
  • Keep metadata per assembly so registrations are not duplicated across generated manifests and runtime precedence remains compatible with the existing assembly scan.
  • Cover generated metadata, client/silo target filtering, complete fallback behavior, custom-provider activation, and incremental invalidation behavior.

This PR moves provider attribute interpretation to build time and avoids full manifest configuration during provider discovery. It still enumerates relevant assemblies and reflects over TypeManifestProviderAttribute to locate generated metadata. #10504 tracks a generated module-initializer registry which will remove that remaining reflection from the normal path while retaining lazy compatibility fallback.

This supersedes #9731 and fixes #9730.

Microsoft Reviewers: Open in CodeFlow

@ReubenBond

Copy link
Copy Markdown
Member Author

I audited the incremental-generator impact and pushed 0a50c9698 to reduce avoidable provider scanning. Provider and application-part assembly attributes are now classified in one pass, without the filtered List/array allocations, and provider-specific incremental caching/invalidation tests were added.

A three-way BenchmarkDotNet comparison used main, the pre-optimization PR generator, and the final generator with 64 synthetic references (8 containing provider registrations). With 15 measurement iterations, both initial generation and an unrelated source edit were statistically Same as main at the 5% threshold. Final allocations were slightly below main (51.61 KB vs 52.35 KB initial; 30.03 KB vs 30.60 KB incremental). The VM timings were noisy, so the equivalence test and allocation results are more reliable than the raw means.

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 shifts RegisterProviderAttribute interpretation into the Orleans incremental source-generator pipeline, emitting lightweight build-time provider metadata and updating client/silo configuration to resolve providers via a shared runtime resolver.

Changes:

  • Introduces IProviderMetadataProvider and generates implementations only when provider metadata exists.
  • Adds ProviderRegistrationResolver and routes both client and silo provider resolution through it (with legacy attribute fallback for older assemblies).
  • Extends codegen models/tests to extract, normalize, and cache provider registration metadata deterministically.
Show a summary per file
File Description
test/Orleans.Core.Tests/ProviderRegistrationResolverTests.cs Adds coverage for generated metadata consumption, legacy fallback, and non-activation of custom manifest providers.
test/Orleans.CodeGenerator.Tests/ModelExtractorTests.cs Verifies provider registrations are extracted (and deterministically ordered) during reference extraction.
test/Orleans.CodeGenerator.Tests/IncrementalModelEqualityTests.cs Extends reference assembly model builder to include provider registrations.
test/Orleans.CodeGenerator.Tests/IncrementalCachingTests.cs Adds incremental caching tests to ensure provider changes invalidate the pipeline and unrelated changes do not.
src/Orleans.Serialization/Configuration/ITypeManifestProvider.cs Introduces the new public IProviderMetadataProvider contract in the serialization configuration namespace.
src/Orleans.Runtime/Hosting/DefaultSiloServices.cs Switches silo provider registration resolution to ProviderRegistrationResolver.
src/Orleans.Core/Core/ProviderRegistrationResolver.cs Adds shared runtime resolver for provider registrations (generated metadata + legacy fallback).
src/Orleans.Core/Core/DefaultClientServices.cs Switches client provider registration resolution to ProviderRegistrationResolver.
src/Orleans.CodeGenerator/ReferenceAssemblyDataProvider.cs Ensures empty reference model includes an empty provider-registration collection.
src/Orleans.CodeGenerator/Model/ReferenceAssemblyModelExtractor.cs Extracts RegisterProviderAttribute metadata and adds it to the reference model with deterministic ordering.
src/Orleans.CodeGenerator/Model/ReferenceAssemblyModel.cs Adds RegisteredProviderModel and stores it on ReferenceAssemblyModel.
src/Orleans.CodeGenerator/Model/MetadataAggregateModelBuilder.cs Normalizes/uniquifies provider registrations for stable incremental caching.
src/Orleans.CodeGenerator/MetadataGenerator.cs Emits IProviderMetadataProvider.ConfigureProviders(...) only when provider registrations exist.
src/Orleans.CodeGenerator/LibraryTypes.cs Adds RegisterProviderAttribute to known library types for extraction.
src/api/Orleans.Serialization/Orleans.Serialization.cs Updates public API surface to include IProviderMetadataProvider.

Review details

Tip

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

  • Files reviewed: 15/15 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread src/Orleans.Core/Core/ProviderRegistrationResolver.cs Outdated
Copilot AI review requested due to automatic review settings August 11, 2026 22:26

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.

Review details

Suppressed comments (2)

src/Orleans.Serialization/Configuration/TypeManifestProviderAttribute.cs:37

  • Same trimming annotation issue as the constructor parameter: ProviderType is consumed for DI registration and should preserve all public constructors.
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
        public Type ProviderType { get; }

src/Orleans.Serialization/Configuration/TypeManifestProviderAttribute.cs:18

  • TypeManifestProviderAttribute.ProviderType is used as an implementation type for DI (SerializerBuilderExtensions.AddAssembly registers it with AddSingleton), so trimming needs to preserve all public constructors, not just a public parameterless ctor. Using PublicParameterlessConstructor here can lead to incorrect trimming annotations and ILLink warnings for custom providers with injected constructors.

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

        public TypeManifestProviderAttribute(
            [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
            Type providerType)
  • Files reviewed: 16/16 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread src/Orleans.Core/Core/ProviderRegistrationResolver.cs Outdated
ReubenBond and others added 7 commits August 11, 2026 15:34
Port provider registration discovery to the current incremental reference-assembly model and consume generated manifest metadata during client and silo configuration.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Retain constructed generic provider types in generated registrations and avoid executing non-OrleansCodeGen manifest providers while collecting provider metadata.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Preserve closed generic provider types, avoid activating custom manifest providers outside DI, and retain a legacy fallback for packages built with older generators.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: dd22afa0-8eac-4b78-bc16-d2f60bc3cb22
Avoid executing full serialization manifests when resolving configuration-driven providers. Generate a lightweight provider metadata contract, preserve legacy attribute fallback, and cover client, silo, and custom-provider behavior.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 90ba28fa-3faa-4c32-a712-d8cb4b5fd3f0
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 90ba28fa-3faa-4c32-a712-d8cb4b5fd3f0
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 90ba28fa-3faa-4c32-a712-d8cb4b5fd3f0
Copilot AI review requested due to automatic review settings August 11, 2026 22:35

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.

Review details

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

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 90ba28fa-3faa-4c32-a712-d8cb4b5fd3f0
Copilot AI review requested due to automatic review settings August 12, 2026 00:08

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.

Review details

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

@ReubenBond
ReubenBond merged commit 1dc0d29 into dotnet:main Aug 12, 2026
134 of 138 checks passed
@github-actions github-actions Bot locked and limited conversation to collaborators Sep 12, 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.

Source Generator should scan for RegisterProvider attributes at build time

2 participants