Skip to content

Commit d4ce8ca

Browse files
committed
[Mono.Android] Guard GREF/WREF logging P/Invokes behind Logger.LogGlobalRef check
The AndroidObjectReferenceManager overrides for CreateGlobalReference, DeleteGlobalReference, CreateWeakGlobalReference, and DeleteWeakGlobalReference were unconditionally calling native logging P/Invokes (_monodroid_gref_log_new, _monodroid_gref_log_delete, _monodroid_weak_gref_new, _monodroid_weak_gref_delete) on every invocation, even when GREF logging was disabled. While the native side does an early return when LOG_GREF is off, the managed-to-native transition itself has measurable overhead that adds up when creating/deleting many references in a tight loop (e.g. during GC bridge processing). This change wraps the P/Invoke calls in `if (Logger.LogGlobalRef)` guards, matching the pattern already used for local reference logging (CreateLocalReference, DeleteLocalReference, etc.). Note: the native counters (gc_gref_count, gc_weak_gref_count) will not be updated when logging is off. These counters are only used for logging output and the GREF threshold GC trigger, both of which are only relevant when logging is enabled.
1 parent e47afe1 commit d4ce8ca

1 file changed

Lines changed: 34 additions & 30 deletions

File tree

src/Mono.Android/Android.Runtime/AndroidRuntime.cs

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -176,18 +176,19 @@ public override void WriteGlobalReferenceLine (string format, params object?[] a
176176

177177
public override JniObjectReference CreateGlobalReference (JniObjectReference value)
178178
{
179-
var r = base.CreateGlobalReference (value);
179+
var r = base.CreateGlobalReference (value);
180180

181-
var log = Logger.LogGlobalRef;
182-
var ctype = log ? GetObjectRefType (value.Type) : (byte) '*';
183-
var ntype = log ? GetObjectRefType (r.Type) : (byte) '*';
184-
var tname = log ? Thread.CurrentThread.Name : null;
185-
var tid = log ? Thread.CurrentThread.ManagedThreadId : 0;
186-
var from = log ? new StringBuilder (new StackTrace (true).ToString ()) : null;
187-
int gc = RuntimeNativeMethods._monodroid_gref_log_new (value.Handle, ctype, r.Handle, ntype, tname, tid, from, 1);
188-
if (gc >= JNIEnvInit.gref_gc_threshold) {
189-
Logger.Log (LogLevel.Warn, "monodroid-gc", gc + " outstanding GREFs. Performing a full GC!");
190-
System.GC.Collect ();
181+
if (Logger.LogGlobalRef) {
182+
var ctype = GetObjectRefType (value.Type);
183+
var ntype = GetObjectRefType (r.Type);
184+
var tname = Thread.CurrentThread.Name;
185+
var tid = Thread.CurrentThread.ManagedThreadId;
186+
var from = new StringBuilder (new StackTrace (true).ToString ());
187+
int gc = RuntimeNativeMethods._monodroid_gref_log_new (value.Handle, ctype, r.Handle, ntype, tname, tid, from, 1);
188+
if (gc >= JNIEnvInit.gref_gc_threshold) {
189+
Logger.Log (LogLevel.Warn, "monodroid-gc", gc + " outstanding GREFs. Performing a full GC!");
190+
System.GC.Collect ();
191+
}
191192
}
192193

193194
return r;
@@ -206,12 +207,13 @@ static byte GetObjectRefType (JniObjectReferenceType type)
206207

207208
public override void DeleteGlobalReference (ref JniObjectReference value)
208209
{
209-
var log = Logger.LogGlobalRef;
210-
var ctype = log ? GetObjectRefType (value.Type) : (byte) '*';
211-
var tname = log ? Thread.CurrentThread.Name : null;
212-
var tid = log ? Thread.CurrentThread.ManagedThreadId : 0;
213-
var from = log ? new StringBuilder (new StackTrace (true).ToString ()) : null;
214-
RuntimeNativeMethods._monodroid_gref_log_delete (value.Handle, ctype, tname, tid, from, 1);
210+
if (Logger.LogGlobalRef) {
211+
var ctype = GetObjectRefType (value.Type);
212+
var tname = Thread.CurrentThread.Name;
213+
var tid = Thread.CurrentThread.ManagedThreadId;
214+
var from = new StringBuilder (new StackTrace (true).ToString ());
215+
RuntimeNativeMethods._monodroid_gref_log_delete (value.Handle, ctype, tname, tid, from, 1);
216+
}
215217

216218
base.DeleteGlobalReference (ref value);
217219
}
@@ -220,25 +222,27 @@ public override JniObjectReference CreateWeakGlobalReference (JniObjectReference
220222
{
221223
var r = base.CreateWeakGlobalReference (value);
222224

223-
var log = Logger.LogGlobalRef;
224-
var ctype = log ? GetObjectRefType (value.Type) : (byte) '*';
225-
var ntype = log ? GetObjectRefType (r.Type) : (byte) '*';
226-
var tname = log ? Thread.CurrentThread.Name : null;
227-
var tid = log ? Thread.CurrentThread.ManagedThreadId : 0;
228-
var from = log ? new StringBuilder (new StackTrace (true).ToString ()) : null;
229-
RuntimeNativeMethods._monodroid_weak_gref_new (value.Handle, ctype, r.Handle, ntype, tname, tid, from, 1);
225+
if (Logger.LogGlobalRef) {
226+
var ctype = GetObjectRefType (value.Type);
227+
var ntype = GetObjectRefType (r.Type);
228+
var tname = Thread.CurrentThread.Name;
229+
var tid = Thread.CurrentThread.ManagedThreadId;
230+
var from = new StringBuilder (new StackTrace (true).ToString ());
231+
RuntimeNativeMethods._monodroid_weak_gref_new (value.Handle, ctype, r.Handle, ntype, tname, tid, from, 1);
232+
}
230233

231234
return r;
232235
}
233236

234237
public override void DeleteWeakGlobalReference (ref JniObjectReference value)
235238
{
236-
var log = Logger.LogGlobalRef;
237-
var ctype = log ? GetObjectRefType (value.Type) : (byte) '*';
238-
var tname = log ? Thread.CurrentThread.Name : null;
239-
var tid = log ? Thread.CurrentThread.ManagedThreadId : 0;
240-
var from = log ? new StringBuilder (new StackTrace (true).ToString ()) : null;
241-
RuntimeNativeMethods._monodroid_weak_gref_delete (value.Handle, ctype, tname, tid, from, 1);
239+
if (Logger.LogGlobalRef) {
240+
var ctype = GetObjectRefType (value.Type);
241+
var tname = Thread.CurrentThread.Name;
242+
var tid = Thread.CurrentThread.ManagedThreadId;
243+
var from = new StringBuilder (new StackTrace (true).ToString ());
244+
RuntimeNativeMethods._monodroid_weak_gref_delete (value.Handle, ctype, tname, tid, from, 1);
245+
}
242246

243247
base.DeleteWeakGlobalReference (ref value);
244248
}

0 commit comments

Comments
 (0)