using System; using System.Reflection; using System.Diagnostics; using System.Runtime.InteropServices; namespace Field { struct Test { public float X; } class MainClass { const int loops = 10000000; Stopwatch m_StopWatch = new Stopwatch(); Test m_Test; object m_Target; object m_Value; FieldInfo m_Field; public MainClass() { m_Target = m_Test; Type t = typeof(Test); m_Field = t.GetField("X"); m_Value = m_Field.GetValue(m_Test); } public void Test1() { m_StopWatch.Reset(); m_StopWatch.Start(); for (int i = 0; i < loops; ++i) { m_Test.X = (float)i; } m_StopWatch.Stop(); Console.WriteLine("Test1: " + m_StopWatch.ElapsedMilliseconds + " ms"); } public unsafe void Test2() { m_StopWatch.Reset(); m_StopWatch.Start(); for (int i = 0; i < loops; ++i) { GCHandle gcHandle = GCHandle.Alloc(m_Value, GCHandleType.Pinned); IntPtr rawPtr = gcHandle.AddrOfPinnedObject(); float* buffer = (float*)rawPtr.ToPointer(); *buffer = (float)i; gcHandle.Free(); m_Field.SetValueDirect(__makeref(m_Test), m_Value); } m_StopWatch.Stop(); Console.WriteLine("Test2: " + m_StopWatch.ElapsedMilliseconds + " ms"); } public unsafe void Test3() { m_StopWatch.Reset(); m_StopWatch.Start(); for (int i = 0; i < loops; ++i) { GCHandle gcHandle = GCHandle.Alloc(m_Value, GCHandleType.Pinned); IntPtr rawPtr = gcHandle.AddrOfPinnedObject(); float* buffer = (float*)rawPtr.ToPointer(); *buffer = (float)i; gcHandle.Free(); m_Field.SetValue(m_Target, m_Value); m_Test = (Test)m_Target; } m_StopWatch.Stop(); Console.WriteLine("Test3: " + m_StopWatch.ElapsedMilliseconds + " ms"); } public static void Main(string[] args) { MainClass main = new MainClass(); main.Test1(); main.Test2(); main.Test3(); Console.ReadKey(); } } }
Xamarin - Release
Test1: 35 ms
Test2: 3237 ms
Test3: 5189 ms