Repository navigation
Add trim-aware runtime EventSource foundation - #12843
Conversation
Introduce the trim-aware Microsoft.Android.Runtime provider contract, wire its private feature switch to EventSource support, and cover metadata, emission, runtime configuration, and trimming behavior. Co-authored-by: Copilot App <[email protected]>
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The provider contract test fails with InvalidCastException, and the reserved event ID coverage and documentation wording need updates.
Get a fresh assessment by requesting another Copilot review.
Review effort: Lite
Findings: 1
Open (3)
What changed in this PR
Adds an opt-in, trim-aware Microsoft.Android.Runtime EventSource foundation for future runtime diagnostics.
Changes:
- Defines provider metadata, reserved IDs, keywords, and diagnostic events.
- Adds feature-switch, runtimeconfig, and trimming support.
- Adds tests and
dotnet-tracedocumentation.
| File | Summary |
|---|---|
tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj |
Enables and includes runtime EventSource tests. |
tests/Mono.Android-Tests/Mono.Android-Tests/Android.Runtime/RuntimeEventSourceTests.cs |
Tests provider metadata and event emission; enum constant casting currently causes InvalidCastException, and reserved IDs 1–6 are not asserted. |
src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/LinkerTests.cs |
Validates runtime configuration, feature switches, and trimming behavior. |
src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.RuntimeConfig.targets |
Emits runtime configuration options. |
src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.DefaultProperties.targets |
Enables EventSource support for the opt-in feature. |
src/Mono.Android/Mono.Android.csproj |
Includes the provider implementation. |
src/Mono.Android/Microsoft.Android.Runtime/RuntimeFeature.cs |
Defines the disabled-by-default feature switch. |
src/Mono.Android/Microsoft.Android.Runtime/RuntimeEventSource.cs |
Implements the lazy EventSource provider and events. |
Documentation/guides/tracing.md |
Documents provider activation and collection; wording should clarify that the runtime option is overridden. |
Handle reflected enum constants correctly, lock the reserved event ID contract in tests, and clarify the runtime EventSource support override in the tracing guide. Co-authored-by: Copilot App <[email protected]>
Remove the Android-specific EventSource opt-in and gate the provider directly on System.Diagnostics.Tracing.EventSource.IsSupported. Update trimming, runtimeconfig, emission tests, and tracing documentation to use EventSourceSupport. Co-authored-by: Copilot App <[email protected]>
|
/review |
|
✅ Android PR Reviewer completed successfully! Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
To allow these domains, add them to the network:
allowed:
- defaults
- "azcliprod.blob.core.windows.net"See Network Configuration for more information.
|
There was a problem hiding this comment.
The trim-aware design is sound: the standard CoreLib feature switch gates a lazy provider holder, the linker test verifies both runtimeconfig propagation and removal/retention of the nested implementation, and the EventListener test validates the emitted IDs, keywords, tasks, and opcodes. Please complete the provider-contract coverage for the second type-map direction as noted inline.
CI is still in progress. The completed Linux/macOS build and Android Tools/Java.Interop lanes are green, with the remaining test matrix still running; this review therefore does not treat CI as green yet.
Warning
Firewall blocked 1 domain
The following domain was blocked by the firewall during workflow execution:
azcliprod.blob.core.windows.net
To allow these domains, add them to the network.allowed list in your workflow frontmatter:
network:
allowed:
- defaults
- "azcliprod.blob.core.windows.net"See Network Configuration for more information.
Generated by Android PR Reviewer for #12843 · copilot · gpt56 · 93.8 AIC · ⌖ 9.76 AIC · ⊞ 17.6K
Comment /review to run again
Remove the GC bridge, type-map, and interop event definitions from the bottom layer. Retain only the gated provider foundation, document the reserved contract for later layers, and verify the provider declares no events. Co-authored-by: Copilot App <[email protected]>
Require future event helpers to guard the standard feature switch directly, validate the complete trimmed call path through a trimmable library, preserve the provider singleton lifetime in tests, and clarify Release defaults. Co-authored-by: Copilot App <[email protected]>
|
/review |
|
✅ Android PR Reviewer completed successfully!
|
There was a problem hiding this comment.
The trim-aware provider foundation is well scoped: the provider is lazy, the standard runtime switch is propagated into runtimeconfig, both enabled and disabled linked outputs are inspected, and the device test verifies provider creation without prematurely defining events. The remaining inline suggestion asks that the newly added production RuntimeFeature.EventSourceSupport wrapper be exercised directly instead of only testing a copied implementation.
CI is still in progress: all 42 completed checks are green, while MSBuild+Emulator 10 remains running and the aggregate dotnet-android check remains queued. This review therefore does not treat CI as fully green yet.
Generated by Android PR Reviewer for #12843 · copilot · gpt56 · 110.8 AIC · ⌖ 9.76 AIC · ⊞ 17.6K
Comment /review to run again
Exercise RuntimeFeature.EventSourceSupport in the on-device provider foundation test so the production wrapper cannot drift independently from the linker fixture. Co-authored-by: Copilot App <[email protected]>
|
/review |
|
✅ Android PR Reviewer completed successfully!
|
There was a problem hiding this comment.
The trim gate, provider metadata, project wiring, and enabled/disabled linker behavior are coherent with the stated foundation scope. I left one inline testing suggestion to lock the claimed lazy provider creation rather than only proving creation on access.
CI is still running: the Android Tools Tests Mac check has passed, while the remaining Azure DevOps checks are queued or in progress.
Generated by Android PR Reviewer for #12843 · copilot · gpt56 · 66.5 AIC · ⌖ 9.76 AIC · ⊞ 17.6K
Comment /review to run again
Assert the EventListener has not observed Microsoft.Android.Runtime before the provider holder is accessed, covering the foundation's lazy initialization contract. Co-authored-by: Copilot App <[email protected]>
|
/review |
|
✅ Android PR Reviewer completed successfully!
|
There was a problem hiding this comment.
✅ LGTM — 0 errors, 0 warnings, 1 suggestion.
The foundation is appropriately scoped: it uses the standard CoreLib feature switch, creates the provider lazily, verifies enabled/disabled runtimeconfig and linked output, and directly tests provider metadata and creation without prematurely defining events. I left one non-blocking inline suggestion to cover the MonoVM trimming path in addition to CoreCLR.
CI is green: all 44 checks passed, including the aggregate dotnet-android Azure DevOps build and license/cla.
Generated by Android PR Reviewer for #12843 · copilot · gpt56 · 93.7 AIC · ⌖ 9.83 AIC · ⊞ 17.6K
Comment /review to run again
## Summary Layer 2 of registered GitHub stack `12855`, built on the EventSource foundation merged by #12843. - emit the reserved `Microsoft.Android.Runtime` GC bridge events (IDs 7/8, keyword `0x8`, task 1) - measure the complete logical bridge round: Start after callback validation and before `EnsureAllContextsAreOurs`; Stop after collected-context processing, `JavaMarshal.FinishCrossReferenceProcessing`, and `AndroidRuntimeInternal.NotifyBridgeProcessingFinished` - evaluate EventSource enablement once at Start, latch it on the dedicated serialized bridge thread, and use that decision at Stop - initialize the enabled provider during bridge setup so the first event does not lazily construct EventSource while a GC is waiting - preserve feature-off trimming of provider initialization and both production call sites - document the boundary and zero-payload contract This intentionally does not add typemap lookup instrumentation, modify `TimingLogger`, or remove/disable `FastTiming`. ## Validation - `Mono.Android.Runtime.csproj` build - `Mono.Android.csproj` build - full Debug local SDK build - `RuntimeEventSourceFeatureSwitch` linker tests: 2 passed - CoreCLR Mono.Android.NET GC bridge/provider tests with `AndroidTypeMapImplementation=llvm-ir`: 3 passed, 1 pre-existing ignored - CoreCLR Mono.Android.NET GC bridge/provider tests with `AndroidTypeMapImplementation=trimmable`: 3 passed, 1 pre-existing ignored ## Stack - Foundation: #12843, merged into `main` - Base: `main` - This layer: #12849 - Next layer: #12851 - Registered GitHub stack: `12855` Co-authored-by: Copilot App <[email protected]>
## Summary Layer 3 of registered GitHub stack `12855`, above #12849 and foundation #12843. - own the complete trimmable typemap provider contract: event IDs 9/10, keyword `0x4`, task 2, and `JavaToManaged` / `ManagedToJava` direction payloads - instrument trimmable typemap cache-population misses in both directions - check `RuntimeFeature.EventSourceSupport` and listener/keyword enablement only inside the `ConcurrentDictionary.GetOrAdd` miss factories - latch Start emission and pair Stop in `finally`, including failed and throwing backend lookups - preserve linker removal when `EventSourceSupport=false` - document exact miss-only semantics and payloads Cache hits perform no feature-switch or EventSource enablement check and emit no events. The Stop payload has no success/found field, matching the provider contract. This layer remains scoped to the trimmable typemap path on the current CoreCLR-only runtime model. It does not add legacy runtime assumptions and does not modify TimingLogger or FastTiming. ## Validation - `./dotnet-local.sh build src/Mono.Android/Mono.Android.csproj -v:minimal` - `./dotnet-local.sh test bin/TestDebug/net10.0/Xamarin.Android.Build.Tests.dll --filter "Name~RuntimeEventSourceFeatureSwitch"` — 2 passed - trimmable CoreCLR on-device `Mono.Android.NET-Tests`, categories `TypeMap,GCBridge` — 7 passed, 1 expected skip - default CoreCLR on-device `Mono.Android.NET-Tests`, category `TypeMap` — 4 expected trimmable-only skips; no default-path timing assertion remains ## Stack - Base: #12849 / `simonrozsival-gc-bridge-timing` - This layer: #12851 - Next layer: #12853 - Registered GitHub stack: `12855`
## Summary - mark `Android.Runtime.TimingLogger` obsolete with guidance to use `Stopwatch` or `EventSource` - replace its native FastTiming-backed implementation with managed monotonic timing while preserving the `Logger.LogTiming` opt-in gate, `monodroid-timing` logcat tag, default message, elapsed format, and idempotent state transitions - remove the remaining `monodroid_timing_start`/`monodroid_timing_stop` declarations, CoreCLR dispatch entries, NativeAOT stubs, and native managed-timing sequence allocator ## Stack Layer 4 of registered GitHub stack `12855`, above #12851, #12849, and #12843. - Base: `main` (the lower layers have merged) - This layer: #12853 - Top layer: #12854 FastTiming instrumentation, timing properties/modes, dump handling, call sites, and FastTiming tests are intentionally retained here and deferred to Layer 5. ## Validation - `Mono.Android.csproj` build with API compatibility checks - `native-clr.csproj` x86_64 build - `native-nativeaot.csproj` x86_64 build The APK descriptions now use the versions from `main`. The Mono runtime and its generated P/Invoke table were removed upstream, so no Mono-specific validation remains in this layer.
## Summary Layer 5 and the top PR of registered GitHub stack `12855`, above merged #12853, #12851, #12849, and #12843. - remove native FastTiming instrumentation, event storage, formatting, summaries, configuration, and self-overhead measurement - remove the shared FastTiming implementation/static library and all CoreCLR timing call sites - remove FastTiming properties/modes, JNI/export dump entrypoint, broadcast receiver, manifest overlay, packaging hooks, and `_AndroidFastTiming` - retain the exact plain `timing` log category for the obsolete managed `Android.Runtime.TimingLogger` - remove the obsolete `FastTimingTests` device test - direct runtime/JIT/loader diagnostics to EventPipe and Android bridge/type-map diagnostics to `Microsoft.Android.Runtime` - refresh CoreCLR APK size references from a local rebuild after rebasing onto current `main` ## Size The four `BuildReleaseArm64` CoreCLR references were regenerated locally after rebasing onto `main` (`64920590083e2d50e0d99d716ce2d82c46bdb4f9`): | Variant | APK delta | `libmonodroid.so` | Delta | Assembly-store delta | |---|---:|---:|---:|---:| | Simple CoreCLR | -12,288 B | 158,792 → 120,096 B | -38,696 B (-24.37%) | +512 B | | Simple CoreCLR + R8 | -16,384 B | 158,792 → 120,096 B | -38,696 B (-24.37%) | +664 B | | XForms CoreCLR | -12,288 B | 151,488 → 120,096 B | -31,392 B (-20.72%) | -192 B | | XForms CoreCLR + R8 | -12,288 B | 151,488 → 120,096 B | -31,392 B (-20.72%) | -200 B | The size matrix passed all four `BuildReleaseArm64` regression tests after copying the freshly generated `.apkdesc` files. The earlier managed-size investigation used isolated merge-base/PR builds and extracted every assembly. It found no managed DLL size growth: all extracted assemblies had identical uncompressed totals before and after this PR. The small assembly-store changes above are compressed/layout differences, not a ~100 KiB managed-code increase. ## Startup Prior balanced startup measurements showed overlapping distributions and no measurable startup effect; no startup regression or improvement is claimed. ## Validation - rebased onto current `main` and resolved `host.cc` plus four APK reference conflicts - full `make all CONFIGURATION=Release` - CoreCLR APK size regression tests: 4 passed - CoreCLR EventSource linker feature-switch tests: 2 passed - CoreCLR `RunWithLogging` property regression test verifies `debug.dotnet.log=default,assembly,timing` - trimmable type-map tests: 1,277 passed, 1 skipped - native no-op incrementality: `_ConfigureRuntimes` and `_BuildAndroidRuntimes` skip with no CMake/Ninja execution - managed `TimingLogger` and lower-layer EventSource/type-map contract sources remain unchanged ## Stack - Final base: `main` - This layer: #12854 - Registered GitHub stack: `12855`



Summary
Add the EventSource/EventPipe provider foundation for runtime diagnostics without defining events or adding production instrumentation call sites.
Microsoft.Android.Runtimeprovider in the trimmableMono.Android.dllSystem.Diagnostics.Tracing.EventSource.IsSupportedfeature switch as the sole compile/trim gateRuntimeFeature.EventSourceSupportwrapper whose fallback matches CoreLib: enabled unless AppContext explicitly disables itEventSourceSupport=falseremoves its implementation and guarded call paths from trimmed Release applications0x1/0x2for Java interop lifecycle/reachability from Add EventPipe interop instrumentation for wrapper lifecycle and GC-bridge reachability #122580x8for GC bridge timing0x4for trimmable type-map timingdotnet-tracetransportScope
This is Layer 1 and the bottom PR of registered GitHub stack
12855:Android.Runtime.TimingLoggerThis layer intentionally does not:
Android.Runtime.TimingLoggerEach concrete event and its call sites are added by the later layer that owns that instrumentation.
Validation
Mono.Android.csprojXamarin.Android.Build.TestsRuntimeEventSourceFeatureSwitch(false/true), including runtimeconfig validation and linked-assembly inspection proving the nested provider implementation is removed whenEventSourceSupport=falseand retained whenEventSourceSupport=trueMono.Android.NET-Tests.csprojwithEventSourceSupport=trueusing the local Android workload