Skip to content

[native] Avoid redundant GC bridge type checks - #12617

Merged
jonathanpeppers merged 1 commit into
mainfrom
simonrozsival-gc-bridge-performance
Sep 1, 2026
Merged

[native] Avoid redundant GC bridge type checks#12617
jonathanpeppers merged 1 commit into
mainfrom
simonrozsival-gc-bridge-performance

Conversation

@simonrozsival

@simonrozsival simonrozsival commented Sep 1, 2026

Copy link
Copy Markdown
Member

Summary

Reduce JNI work in the shared CoreCLR/NativeAOT GC bridge without changing its reachability algorithm or reference lifecycle.

  • Reuse a successful IGCUserPeer check for subsequent cross-references from the same source during a bridge round.
  • Treat temporary GCUserPeer instances as already known implementations.
  • Skip the redundant Release IsInstanceOf before monodroidClearReferences; retain a Debug assertion documenting and checking the invariant.
  • Remove the now-unused missing-clear-method diagnostic path.

refs_added is set only after add_reference has verified that the source implements IGCUserPeer, and it is reset after references are cleared. It therefore also acts as per-round proof that later interface dispatch is valid.

Observed workload

A .NET MAUI --sample-content startup capture contained 99 bridge cross-references. Fourteen discarded PlatformGraphicsView instances each had seven outgoing edges, so this change removes 84 repeated pre-GC IsInstanceOf calls; one surviving source also avoids its redundant post-GC check, for approximately 85 fewer JNI checks in that round.

Physical-device startup A/B

Measured on a Samsung S23 (API 36, arm64, 60 Hz) using otherwise identical Release CoreCLR dotnet new maui --sample-content APKs. ReadyToRun was disabled in both arms because the exact preview SDK's Crossgen2 package was unavailable.

Method:

  • 80 measured cold-process launches: 40 baseline and 40 optimized.
  • Balanced A/B/B/A followed by B/A/A/B block order, 10 samples per block.
  • pm clear and cmd package compile -f -m speed after every APK switch.
  • Three warmups per block; am start -W -S TotalTime recorded.
  • Device battery temperature recorded with every sample.

The final hot blocks reached 42.1 °C and produced asymmetric thermal outliers, so the thermally controlled subset (all 60 samples at or below 41.0 °C) is the useful comparison:

Startup TotalTime Baseline Optimized Delta
Mean 1,485.5 ms 1,469.0 ms -16.4 ms (-1.1%)
Median 1,472.5 ms 1,467.0 ms -5.5 ms (-0.4%)

A sample-level bootstrap gave a 95% interval of -31.1 to -3.7 ms for the mean and -25.0 to +0.5 ms for the median. This supports no startup regression and a modest favorable signal, but the effect is small relative to whole-app launch variance; the PR's direct claim remains the observed JNI-call reduction.

Raw measurements are preserved in the Copilot session artifact maui-gc-benchmark/startup-results-s23-all.csv.

Validation

  • CoreCLR native hosts compiled and linked for Android arm, arm64, and x64.
  • NativeAOT arm64 Release host compiled and linked through its configured Ninja build.
  • The MAUI sample-content app built and completed repeated cold launches on both an API-35 arm64 emulator and the physical API-36 S23, exercising the 99-edge bridge round.

Reuse successful IGCUserPeer checks for repeated cross-reference sources and skip the redundant release check before clearing references.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI lite review requested due to automatic review settings September 1, 2026 09:58

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.

Copilot review overview

🟡 Changes recommended

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review tier: Lite
Findings: 2 Low severity

New issues introduced by this change (2)
Severity Finding
Low severity src/​native/​clr/​host/​bridge-processing.cc — 🤖 ❌ error Error handling — The log message references a non-existent method name…
Low severity src/​native/​clr/​host/​bridge-processing.cc — 🤖 💡 suggestion Formatting — Repo convention is to annotate #endif with its condition for…
What changed in this PR

This PR optimizes the native GC bridge’s cross-reference processing by avoiding redundant IGCUserPeer type checks within a single bridge round, while keeping the existing reachability semantics and reference lifecycle intact.

Changes:

  • Added a per-round “known IGCUserPeer” fast-path to skip repeated IsInstanceOf checks for subsequent edges from the same source.
  • Treated temporary GCUserPeer instances as already-known IGCUserPeer implementations for cross-reference additions.
  • Removed the Release-path IsInstanceOf guard before monodroidClearReferences, retaining a Debug-only invariant assertion, and removed the unused “missing clear method” diagnostic path.
File Description
src/​native/​clr/​include/​host/​bridge-processing.hh Extends the cross-reference target API and add_reference signature to support caching/fast-path behavior.
src/​native/​clr/​host/​bridge-processing.cc Implements the fast-path logic, updates reference-clearing invariants, and removes the redundant clear-method diagnostic path.
Suppressed comments (1)

src/native/clr/host/bridge-processing.cc:483

  • 🤖 ❌ error Error handling — This debug log string also uses monodroidAddReferences (plural), but the interface method name is monodroidAddReference (singular). Aligning the message with the real method name avoids confusion when diagnosing bridge failures.
	log_errorf (LOG_GC, "Missing monodroidAddReferences method for object of class %s", optional_string (class_name));

Comment thread src/native/clr/host/bridge-processing.cc
Comment thread src/native/clr/host/bridge-processing.cc
@simonrozsival

Copy link
Copy Markdown
Member Author

/review

@simonrozsival simonrozsival added the ready-to-review This PR is ready to review/merge, I think any CI failures are just flaky (ignorable). label Sep 1, 2026
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Android PR Reviewer completed successfully!

Generated by Android PR Reviewer for #12617

@github-actions github-actions Bot 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.

✅ LGTM

The refs_added fast path preserves the GC-bridge lifecycle invariant: it is set only after successful IGCUserPeer verification, cleared for surviving peers after callback cleanup, and irrelevant for collected contexts that are released. Temporary peers are also valid known implementations. The performance claim is appropriately scoped and backed by direct JNI-call observations and device measurements.

Findings: 0 errors · 0 warnings · 1 suggestion. All 45 CI checks completed successfully.

Generated by Android PR Reviewer for #12617 · gpt56 · 92.7 AIC · ⌖ 8.85 AIC · ⊞ 25.7K
Comment /review to run again

// refs_added is set only after add_reference verifies that the source implements IGCUserPeer.
#if DEBUG
abort_unless (env->IsInstanceOf (handle, IGCUserPeer_class), "Object with added references must implement IGCUserPeer");
#endif

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.

🤖 💡 Formatting — Please annotate this newly added directive as #endif // DEBUG, as required by the repository convention for conditional-compilation blocks. This also keeps the invariant assertion’s scope explicit during future edits.

Rule: Annotate #else/#endif (Postmortem #37)

@jonathanpeppers
jonathanpeppers merged commit 75ee946 into main Sep 1, 2026
45 checks passed
@jonathanpeppers
jonathanpeppers deleted the simonrozsival-gc-bridge-performance branch September 1, 2026 12:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-to-review This PR is ready to review/merge, I think any CI failures are just flaky (ignorable).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants