Last active
February 9, 2016 11:30
-
-
Save KrzysFR/df60a94128af8f40bcda to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Doxense.Benchmarks.Perfs | |
{ | |
using System; | |
using System.Diagnostics; | |
using System.Runtime.CompilerServices; | |
using System.Runtime.InteropServices; | |
using BenchmarkDotNet; | |
using BenchmarkDotNet.Tasks; | |
using DotNetCross.Memory; | |
/// <summary>Unmanaged struct with variable size, usually allocated on unmanaged heap</summary> | |
[StructLayout(LayoutKind.Sequential, Pack = 1)] | |
public unsafe struct VarKey | |
{ | |
public uint SomeHeader; // some reandom headers | |
public ushort Size; // size (in bytes) of data immediately after the headers | |
private byte Byte0; // helper field to get address of data start | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
public static USlice GetKeyStatic(VarKey* key) | |
{ | |
return new USlice(&key->Byte0, key->Size); | |
} | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] // probably not going to be effective? | |
public USlice GetKeyFixed() | |
{ | |
fixed (byte* ptr = &this.Byte0) | |
{ | |
return new USlice(ptr, this.Size); | |
} | |
} | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
public USlice GetKeyUnsafeAsPointer() | |
{ | |
return new USlice((byte*) Unsafe.AsPointer(ref this.Byte0), this.Size); | |
} | |
} | |
/// <summary>Equivalent of ArraySegment<byte> but for unmanaged buffers</summary> | |
public unsafe struct USlice | |
{ | |
public byte* Data; | |
public uint Count; | |
public USlice(byte* data, uint count) | |
{ | |
this.Data = data; | |
this.Count = count; | |
} | |
public byte[] GetBytes() | |
{ | |
if (this.Count == 0) return Array.Empty<byte>(); | |
var tmp = new byte[this.Count]; | |
fixed (byte* ptr = &tmp[0]) | |
{ | |
Buffer.MemoryCopy(this.Data, ptr, tmp.Length, this.Count); | |
} | |
return tmp; | |
} | |
} | |
[BenchmarkTask(platform: BenchmarkPlatform.X64, jitVersion: BenchmarkJitVersion.RyuJit, warmupIterationCount: 3, targetIterationCount: 5, processCount: 2)] | |
public unsafe class UnsafeMemoryBench | |
{ | |
private static readonly byte[] LoHBuffer = new byte[1024 * 1024]; // on LoH so should not move around in memory | |
private byte* m_base; | |
private VarKey* m_ptr; | |
[Setup] | |
public void Configure() | |
{ | |
fixed (byte* ptr = &LoHBuffer[0]) | |
{ | |
//hack: buffer is in LOH so should not move around | |
m_base = ptr; | |
} | |
m_ptr = (VarKey*) m_base + 256; | |
m_ptr->SomeHeader = 1234; | |
m_ptr->Size = 43; | |
//// test calls ( | |
//Debugger.Launch(); | |
//USlice x; | |
//x = Static(); | |
//x = Instance_Fixed(); | |
//x = Instance_AsPointer(); | |
} | |
[Benchmark] | |
//[MethodImpl(MethodImplOptions.NoInlining)] | |
public USlice Static() | |
{ | |
return VarKey.GetKeyStatic(m_ptr); | |
} | |
[Benchmark] | |
//[MethodImpl(MethodImplOptions.NoInlining)] | |
public USlice Instance_Fixed() | |
{ | |
return m_ptr->GetKeyFixed(); | |
} | |
[Benchmark] | |
//[MethodImpl(MethodImplOptions.NoInlining)] | |
public USlice Instance_AsPointer() | |
{ | |
return m_ptr->GetKeyUnsafeAsPointer(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment