Skip to content

[bgen] Cache attribute lookups to reduce memory allocations#25782

Draft
rolfbjarne wants to merge 10 commits into
mainfrom
dev/rolf/bgen-attrib-caching
Draft

[bgen] Cache attribute lookups to reduce memory allocations#25782
rolfbjarne wants to merge 10 commits into
mainfrom
dev/rolf/bgen-attrib-caching

Conversation

@rolfbjarne

@rolfbjarne rolfbjarne commented Jun 23, 2026

Copy link
Copy Markdown
Member

Cache various attribute query results in bgen to avoid repeated reflection and
attribute conversion work. This reduces total memory allocations by ~22% and
GC pressure by ~25-39% when generating bindings.

Changes:

  • Cache GetCustomAttributes<T> results per (provider, type) pair
  • Cache HasAttribute<T> results to avoid repeated GetCustomAttributesData() calls
  • Cache common platform attributes as singletons in AttributeFactory
  • Cache GetAllParentAttributes results per MemberInfo
  • Cache ConstructorInfo lookups per (type, argTypes) to avoid repeated reflection
  • Cache static Type[] arrays for attribute constructors
  • Cache getter/setter ExportAttribute results per PropertyInfo

Performance (tvOS bindings, 3-run averages):

Metric Before After Diff
Time 23.9s 20.9s -12.5%
Allocs 7003MB 5439MB -22.3%
Gen0 1268 951 -25.0%
Gen1 414 254 -38.6%

rolfbjarne and others added 7 commits June 23, 2026 15:09
GetCustomAttributes<T> was being called repeatedly on the same providers.
Each call would re-invoke GetCustomAttributesData, iterate all attributes,
and re-instantiate matching ones. Cache results in a
Dictionary<(ICustomAttributeProvider, Type), object> so subsequent queries
for the same provider+type return instantly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add a Dictionary<(ICustomAttributeProvider, Type), bool> cache for
HasAttribute<T> queries. This method is called thousands of times per
platform with the same arguments. Caching the boolean result avoids
repeated GetCustomAttributesData() + type comparison work.

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

Cache no-version/no-message IntroducedAttribute and UnavailableAttribute
instances as static singletons (one per platform). Return cached instances
from CreateNoVersionSupportedAttribute, CreateUnsupportedAttribute, and
CloneFromOtherPlatform when applicable, avoiding repeated heap allocations
for identical platform attributes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Cache GetAllParentAttributes results per MemberInfo context. Since callers
only read from the returned list (never mutate it), the cached list can be
safely shared across multiple callers with the same context. This avoids
re-walking the parent chain and re-querying attributes for the same member
on repeated calls.

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

- Cache Type[] arrays for attribute constructors to avoid repeated allocations
- Cache ConstructorInfo lookups per (type, argTypes) to avoid repeated reflection
- Cache Version objects in AvailabilityBaseAttribute to avoid creating new instances
  for the same version values

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Cache the ExportAttribute lookups for property getters and setters to avoid
repeated attribute queries on the same PropertyInfo.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@rolfbjarne rolfbjarne requested a review from Copilot June 23, 2026 13:37
@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

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 bgen performance by adding several reflection/attribute-related caches to reduce repeated allocations and GC pressure during binding generation.

Changes:

  • Cache ExportAttribute lookups for property getters/setters and cache parent availability attribute traversal in Generator.
  • Cache GetCustomAttributes<T> and HasAttribute<T> results in AttributeManager to avoid repeated reflection and attribute conversion.
  • Add constructor/argument caching in AttributeFactory/AttributeFactory.ConstructorArguments and reuse singleton availability attributes for common no-version cases.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
src/bgen/Generator.cs Adds caches for getter/setter ExportAttribute lookups and parent availability attribute collection.
src/bgen/AttributeManager.cs Adds per-(provider,type) caches for GetCustomAttributes<T> and HasAttribute<T>.
src/bgen/AttributeFactory.cs Caches attribute constructor lookups and reuses singleton no-version availability attributes.
src/bgen/AttributeFactory.ConstructorArguments.cs Reuses static Type[] constructor signature arrays to avoid repeated allocations.

Comment thread src/bgen/AttributeFactory.cs Outdated
@vs-mobiletools-engineering-service2

This comment has been minimized.

Move the constructorCache dictionary from the static AttributeFactory class
to the instance-based AttributeManager class. This eliminates the static
mutable state that could be problematic when tests run in parallel.

The cache is passed through to AttributeFactory and AttributeConversionManager
methods as a parameter. Convenience overloads without the parameter are kept
for test compatibility (they use a static fallback cache).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@vs-mobiletools-engineering-service2

This comment has been minimized.

rolfbjarne and others added 2 commits June 23, 2026 19:25
Remove the two convenience CreateNewAttribute overloads (that didn't take an
AttributeManager parameter) and the static defaultConstructorCache they used.
Remove the corresponding tests that called those overloads.

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

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

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Comment thread src/bgen/AttributeFactory.cs
Comment on lines 8 to 10
[TestFixture]
[Parallelizable (ParallelScope.All)]
public class AttributeFactoryTests {
Comment on lines 511 to +522
public virtual T [] GetCustomAttributes<T> (ICustomAttributeProvider? provider) where T : System.Attribute
{
return FilterAttributes<T> (GetAttributes (provider), provider);
if (provider is null)
return Array.Empty<T> ();

var key = (provider, typeof (T));
if (attributeCache.TryGetValue (key, out var cached))
return (T []) cached;

var result = FilterAttributes<T> (GetAttributes (provider), provider);
attributeCache [key] = result;
return result;
@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

✅ [PR Build #f1dfcf9] Build passed (Detect API changes) ✅

Pipeline on Agent
Hash: f1dfcf91f9f34c52d3007c3b181af4a40c780fea [PR build]

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

✅ [PR Build #f1dfcf9] Build passed (Build packages) ✅

Pipeline on Agent
Hash: f1dfcf91f9f34c52d3007c3b181af4a40c780fea [PR build]

@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

✅ API diff for current PR / commit

NET (empty diffs)

✅ API diff vs stable

NET (empty diffs)

ℹ️ Generator diff

Generator Diff: vsdrops (html) vsdrops (raw diff) gist (raw diff) - Please review changes)

Pipeline on Agent
Hash: f1dfcf91f9f34c52d3007c3b181af4a40c780fea [PR build]

@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

✅ [PR Build #f1dfcf9] Build passed (Build macOS tests) ✅

Pipeline on Agent
Hash: f1dfcf91f9f34c52d3007c3b181af4a40c780fea [PR build]

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

🚀 [CI Build #f1dfcf9] Test results 🚀

Test results

✅ All tests passed on VSTS: test results.

🎉 All 207 tests passed 🎉

Tests counts

✅ assembly-processing: All 1 tests passed. Html Report (VSDrops) Download
✅ cecil: All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (iOS): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (MacCatalyst): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (macOS): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (Multiple platforms): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (tvOS): All 1 tests passed. Html Report (VSDrops) Download
✅ framework: All 2 tests passed. Html Report (VSDrops) Download
✅ fsharp: All 4 tests passed. Html Report (VSDrops) Download
✅ generator: All 5 tests passed. Html Report (VSDrops) Download
✅ interdependent-binding-projects: All 4 tests passed. Html Report (VSDrops) Download
✅ introspection: All 4 tests passed. Html Report (VSDrops) Download
✅ linker (iOS): All 15 tests passed. [attempt 2] Html Report (VSDrops) Download
✅ linker (MacCatalyst): All 15 tests passed. Html Report (VSDrops) Download
✅ linker (macOS): All 21 tests passed. Html Report (VSDrops) Download
✅ linker (tvOS): All 15 tests passed. Html Report (VSDrops) Download
✅ monotouch (iOS): All 20 tests passed. Html Report (VSDrops) Download
✅ monotouch (MacCatalyst): All 19 tests passed. Html Report (VSDrops) Download
✅ monotouch (macOS): All 20 tests passed. [attempt 2] Html Report (VSDrops) Download
✅ monotouch (tvOS): All 20 tests passed. [attempt 2] Html Report (VSDrops) Download
✅ msbuild: All 2 tests passed. Html Report (VSDrops) Download
✅ sharpie: All 1 tests passed. Html Report (VSDrops) Download
✅ windows: All 3 tests passed. Html Report (VSDrops) Download
✅ xcframework: All 4 tests passed. Html Report (VSDrops) Download
✅ xtro: All 1 tests passed. Html Report (VSDrops) Download

macOS tests

✅ Tests on macOS Monterey (12): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Ventura (13): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Sonoma (14): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Sequoia (15): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Tahoe (26): All 5 tests passed. Html Report (VSDrops) Download

Linux Build Verification

Linux build succeeded

Pipeline on Agent
Hash: f1dfcf91f9f34c52d3007c3b181af4a40c780fea [PR build]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants