diff --git a/tests/Java.Interop-PerformanceTests/Java.Interop/JavaTiming.cs b/tests/Java.Interop-PerformanceTests/Java.Interop/JavaTiming.cs index a4104ac70..354153225 100644 --- a/tests/Java.Interop-PerformanceTests/Java.Interop/JavaTiming.cs +++ b/tests/Java.Interop-PerformanceTests/Java.Interop/JavaTiming.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Collections.Concurrent; +using System.Threading; using Java.Interop; using Java.Interop.GenericMarshaler; @@ -36,6 +37,49 @@ public unsafe JavaTiming () Construct (ref peer, JniObjectReferenceOptions.CopyAndDispose); } + public static int StaticReadonlyField_NoCache { + get { + const string __id = "STATIC_READONLY_FIELD.I"; + var __v = _members.StaticFields.GetInt32Value (__id); + return __v; + } + } + + static int? _StaticReadonlyField_Cache; + public static int StaticReadonlyField_ThreadUnsafeCache { + get { + if (_StaticReadonlyField_Cache.HasValue) + return _StaticReadonlyField_Cache.Value; + const string __id = "STATIC_READONLY_FIELD.I"; + var __v = _members.StaticFields.GetInt32Value (__id); + return (int) (_StaticReadonlyField_Cache = __v); + } + } + static int _StaticReadonlyField_haveValue; + static int _StaticReadonlyField_value; + + public static int StaticReadonlyField_ThreadSafeCache { + get { + if (1 == Interlocked.CompareExchange (ref _StaticReadonlyField_haveValue, 1, 0)) + return _StaticReadonlyField_value; + const string __id = "STATIC_READONLY_FIELD.I"; + var __v = _members.StaticFields.GetInt32Value (__id); + return _StaticReadonlyField_value = __v; + } + } + + static ReadOnlyProperty _rop_StaticReadonlyField = new ReadOnlyProperty (); + public static unsafe int StaticReadonlyField_Rop { + get { + static int _GetInt32Value (string encodedMember) + { + return _members.StaticFields.GetInt32Value (encodedMember); + } + delegate *managed c = &_GetInt32Value; + return _rop_StaticReadonlyField.GetValue (c, "STATIC_READONLY_FIELD.I"); + } + } + static JniMethodInfo svm; public static void StaticVoidMethod () { diff --git a/tests/Java.Interop-PerformanceTests/Java.Interop/ReadOnlyPropertyTiming.cs b/tests/Java.Interop-PerformanceTests/Java.Interop/ReadOnlyPropertyTiming.cs new file mode 100644 index 000000000..f0bc18903 --- /dev/null +++ b/tests/Java.Interop-PerformanceTests/Java.Interop/ReadOnlyPropertyTiming.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.Linq; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Threading; + +using Java.Interop; + +using NUnit.Framework; + +namespace Java.Interop.PerformanceTests { + + + [TestFixture] + class ReadOnlyPropertyTiming : Java.InteropTests.JavaVMFixture { + [Test] + public void StaticReadOnlyPropertyTiming () + { + const int count = 1000; + + var noCache = Stopwatch.StartNew (); + for (int i = 0; i < count; ++i) { + _ = JavaTiming.StaticReadonlyField_NoCache; + } + noCache.Stop (); + + var badCache = Stopwatch.StartNew (); + for (int i = 0; i < count; ++i) { + _ = JavaTiming.StaticReadonlyField_ThreadUnsafeCache; + } + badCache.Stop (); + + var goodCache = Stopwatch.StartNew (); + for (int i = 0; i < count; ++i) { + _ = JavaTiming.StaticReadonlyField_ThreadSafeCache; + } + goodCache.Stop (); + + var ropCache = Stopwatch.StartNew (); + for (int i = 0; i < count; ++i) { + _ = JavaTiming.StaticReadonlyField_Rop; + } + ropCache.Stop (); + + Console.WriteLine ("Static ReadOnly Property Lookup + Invoke Timing:"); + Console.WriteLine ("\t No caching: {0}, {1} ticks", noCache.Elapsed, noCache.ElapsedTicks / count); + Console.WriteLine ("\t Thread Unsafe Cache: {0}, {1} ticks", badCache.Elapsed, badCache.ElapsedTicks / count); + Console.WriteLine ("\t Thread-Safe Cache: {0}, {1} ticks", goodCache.Elapsed, goodCache.ElapsedTicks / count); + Console.WriteLine ("\tReadOnlyProperty Cache: {0}, {1} ticks", ropCache.Elapsed, ropCache.ElapsedTicks / count); + } + } + + struct ReadOnlyProperty { + int have_value; + T value; + + [MethodImpl (MethodImplOptions.AggressiveInlining)] + public unsafe T GetValue (delegate *managed c, string encodedMember) + { + if (1 == Interlocked.CompareExchange (ref have_value, 1, 0)) + return value; + var __v = c (encodedMember); + value = __v; + return value; + } + } +} \ No newline at end of file diff --git a/tests/Java.Interop-PerformanceTests/java/com/xamarin/interop/performance/JavaTiming.java b/tests/Java.Interop-PerformanceTests/java/com/xamarin/interop/performance/JavaTiming.java index ca45b787d..60671befb 100644 --- a/tests/Java.Interop-PerformanceTests/java/com/xamarin/interop/performance/JavaTiming.java +++ b/tests/Java.Interop-PerformanceTests/java/com/xamarin/interop/performance/JavaTiming.java @@ -2,6 +2,13 @@ public class JavaTiming { + public static final int STATIC_READONLY_FIELD = getStaticReadonlyFieldValue (); + + static int getStaticReadonlyFieldValue () + { + return 42; + } + public static void StaticVoidMethod () { }