Skip to content

[Mono.Android] Avoid lock for activation constructor cache - #12409

Open
jonathanpeppers wants to merge 2 commits into
mainfrom
jonathanpeppers-audit-android-lock-caches
Open

[Mono.Android] Avoid lock for activation constructor cache#12409
jonathanpeppers wants to merge 2 commits into
mainfrom
jonathanpeppers-audit-android-lock-caches

Conversation

@jonathanpeppers

@jonathanpeppers jonathanpeppers commented Aug 17, 2026

Copy link
Copy Markdown
Member

Summary

  • replace the monitor-protected TypeManager activation-constructor cache with a deliberately small ConcurrentDictionary
  • use one stateful GetOrAdd call while preserving constructor trimming annotations without suppressions
  • add an Android in-process BenchmarkDotNet benchmark for the exact cached CreateProxy path

Follow-up to #12377.

Results

Measured on a Pixel 10 running Android 16 with CoreCLR:

Check Baseline Changed Difference
Cached CreateProxy benchmark 1,435.996 ns 1,341.401 ns -94.594 ns (-6.59%)
MAUI cold-start mean, 40 paired runs 371.750 ms 369.925 ms -1.825 ms
Final APK size 19,262,495 bytes 19,262,495 bytes 0 bytes

The benchmark uses an unregistered JNI jstring global reference so each iteration exercises normal managed activation without duplicate-peer detection. The cold-start paired changed-minus-base 95% confidence interval is [-7.842, +4.192] ms, indicating no measurable startup regression.

apkdiff reports only a 32-byte uncompressed increase in libassembly-store.so; this does not change final APK size. Extracted Mono.Android.dll remains 1,913,344 bytes.

Validation

  • Release SDK build, with no new trim warnings
  • ReflectionCreateProxy device fixture: 3 passed, 0 failed
  • Android in-process BenchmarkDotNet run
  • controlled MAUI/CoreCLR APK build with the baseline package lock
  • 40 counterbalanced AB/BA cold-start pairs

Copilot AI lite review requested due to automatic review settings August 17, 2026 18:29
Use a ConcurrentDictionary stateful factory so cached proxy activation lookups no longer enter a monitor while preserving constructor trim annotations.

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

Copilot-Session: bafa7c78-cb0c-45a5-9ec0-65cecea94620
@jonathanpeppers
jonathanpeppers force-pushed the jonathanpeppers-audit-android-lock-caches branch from 2e90263 to 6fb9a22 Compare August 17, 2026 18:30
@jonathanpeppers
jonathanpeppers changed the base branch from jonathanpeppers-cache-jni-method-ids to main August 17, 2026 18:31

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 updates the Mono.Android activation path to remove monitor-based locking around the activation-constructor cache by switching it to a small ConcurrentDictionary, while preserving trimming annotations. It also adds an Android in-process BenchmarkDotNet benchmark intended to measure the cached TypeManager.CreateProxy path.

Changes:

  • Replaced the lock-protected Dictionary<Type, ActivationConstructor> cache with a small ConcurrentDictionary and a single stateful GetOrAdd factory.
  • Added an AnnotatedType wrapper to preserve DynamicallyAccessedMembers flow through the GetOrAdd state parameter.
  • Added an Android BenchmarkDotNet benchmark targeting the cached CreateProxy activation path.

Reviewed changes

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

File Description
tests/Android.Benchmarks/ActivationConstructorCacheBenchmarks.cs Adds a new on-device benchmark for the cached TypeManager.CreateProxy path.
src/Mono.Android/Java.Interop/TypeManager.cs Reworks activation-constructor caching to be lock-free for reads via ConcurrentDictionary.GetOrAdd while keeping trimming annotations.

Comment thread tests/Android.Benchmarks/ActivationConstructorCacheBenchmarks.cs Outdated
Use an unmanaged jstring global reference so the CreateProxy benchmark exercises normal managed activation instead of duplicate-peer detection.

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

Copilot-Session: bafa7c78-cb0c-45a5-9ec0-65cecea94620
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