8000 [NativeAOT] Initialize GC threshold much earlier by grendello · Pull Request #10488 · dotnet/android · GitHub
[go: up one dir, main page]

Skip to content

Conversation

grendello
Copy link
Contributor

The threshold value is used by the global reference creation routine to determine whether to start GC collection:

if (gc >= JNIEnvInit.gref_gc_threshold) {
  Logger.Log (LogLevel.Debug, "monodroid-gc", gc + " outstanding GREFs. Performing a full GC!");
  System.GC.Collect ();
}

However, the threshold value was being initialized after we've already invoked some non-trivial managed code in the managed NativeAOT runtime, too late to avoid at least a handful of System.GC.Collect () calls:

09-15 14:37:25.923 10761 10761 D monodroid-gc: 1 outstanding GREFs. Performing a full GC!
09-15 14:37:25.923 10761 10761 D monodroid-gc: 2 outstanding GREFs. Performing a full GC!
09-15 14:37:25.923 10761 10761 D monodroid-gc: 3 outstanding GREFs. Performing a full GC!
09-15 14:37:25.924 10761 10761 D monodroid-gc: 3 outstanding GREFs. Performing a full GC!

Fix this by splitting the GC threshold value initialization into a separate method which is invoked as soon as possible from the JNI_OnLoad function exported by the NativeAOT application.

The threshold value is used by the global reference creation
routine to determine whether to [start GC collection][0]:

```csharp
if (gc >= JNIEnvInit.gref_gc_threshold) {
  Logger.Log (LogLevel.Debug, "monodroid-gc", gc + " outstanding GREFs. Performing a full GC!");
  System.GC.Collect ();
}
```

However, the threshold value was being initialized after we've already invoked some non-trivial
managed code in the managed [NativeAOT runtime][1], too late to avoid at least a handful of
`System.GC.Collect ()` calls:

    09-15 14:37:25.923 10761 10761 D monodroid-gc: 1 outstanding GREFs. Performing a full GC!
    09-15 14:37:25.923 10761 10761 D monodroid-gc: 2 outstanding GREFs. Performing a full GC!
    09-15 14:37:25.923 10761 10761 D monodroid-gc: 3 outstanding GREFs. Performing a full GC!
    09-15 14:37:25.924 10761 10761 D monodroid-gc: 3 outstanding GREFs. Performing a full GC!

Fix this by splitting the GC threshold value initialization into a separate method which is
invoked as soon as possible from the `JNI_OnLoad` function exported by the NativeAOT application.

[0]: https://github.com/dotnet/android/blob/e72bf3626024fd1e27dd9cd26d7f8439bc088e19/src/Mono.Android/Android.Runtime/AndroidRuntime.cs#L178-L195
[1]: https://github.com/dotnet/android/blob/e72bf3626024fd1e27dd9cd26d7f8439bc088e19/src/Microsoft.Android.Runtime.NativeAOT/Android.Runtime.NativeAOT/JavaInteropRuntime.cs#L60
Copy link
@Copilot Copilot AI left a comment

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 fixes a timing issue in NativeAOT where the GC threshold was being initialized too late, causing unnecessary garbage collection calls during early runtime initialization.

  • Splits GC threshold initialization into a separate method called earlier in the process
  • Adds explicit early initialization call in NativeAOT's JNI_OnLoad function
  • Removes redundant GC threshold initialization from the main InitializeJniRuntime method

Reviewed Changes

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

File Description
src/Mono.Android/Android.Runtime/JNIEnvInit.cs Extracts GC threshold initialization into new NativeAotInitializeMaxGrefGet method and removes it from InitializeJniRuntime
src/Microsoft.Android.Runtime.NativeAOT/Android.Runtime.NativeAOT/JavaInteropRuntime.cs Calls the new GC threshold initialization method early in JNI_OnLoad before other initialization

Copy link
Member
@filipnavara filipnavara left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested on our app, the inital 4 GCs with "outstanding GREFs. Performing a full GC!" message are gone.

Copy link
Member
@jonathanpeppers jonathanpeppers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm rerunning these, but if they end up passing, this looks good:

Image

There are some other test failures caused by Android 36.1 changes, hopefully I can fix shortly.

@jonathanpeppers jonathanpeppers merged commit 8746ec5 into main Sep 15, 2025
55 of 59 checks passed
@jonathanpeppers jonathanpeppers deleted the dev/grendel/naot-early-gc-init branch September 15, 2025 21:14
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.

3 participants

0