Skip to content

Instantly share code, notes, and snippets.

@KrzysFR
Last active February 9, 2016 11:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save KrzysFR/df60a94128af8f40bcda to your computer and use it in GitHub Desktop.
Save KrzysFR/df60a94128af8f40bcda to your computer and use it in GitHub Desktop.
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&lt;byte&gt; 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