using BenchmarkDotNet.Attributes; using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace TensorFlowBenchmark.Unmanaged { public struct UnmanagedStruct { public int a; public long b; public UnmanagedStruct(int _) { a = 2; b = 3; } } [SimpleJob(launchCount: 1, warmupCount: 2)] [MinColumn, MaxColumn, MeanColumn, MedianColumn] public unsafe class StructCastBenchmark { private static void EnsureIsUnmanaged(T _) where T : unmanaged { } static StructCastBenchmark() //if UnmanagedStruct is not unmanaged struct then this will fail to compile. => EnsureIsUnmanaged(new UnmanagedStruct()); private IntPtr data; private void* dataptr; [GlobalSetup] public void Setup() { data = Marshal.AllocHGlobal(Marshal.SizeOf()); dataptr = data.ToPointer(); } [Benchmark, MethodImpl(MethodImplOptions.NoOptimization)] public void Marshal_PtrToStructure() { UnmanagedStruct _; for (int i = 0; i < 10000; i++) { _ = Marshal.PtrToStructure(data); } } [Benchmark, MethodImpl(MethodImplOptions.NoOptimization)] public void PointerCast() { var dptr = dataptr; UnmanagedStruct _; for (int i = 0; i < 10000; i++) { _ = *(UnmanagedStruct*)dptr; } } [Benchmark, MethodImpl(MethodImplOptions.NoOptimization)] public void Unsafe_Read() { var dptr = dataptr; UnmanagedStruct _; for (int i = 0; i < 10000; i++) { _ = Unsafe.Read(dptr); } } } }