Skip to content

Instantly share code, notes, and snippets.

@teoadal
Last active July 20, 2022 15:02
Show Gist options
  • Save teoadal/e826cef1e5b2677fcaf1b23b3383a248 to your computer and use it in GitHub Desktop.
Save teoadal/e826cef1e5b2677fcaf1b23b3383a248 to your computer and use it in GitHub Desktop.
using System;
using System.Buffers;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
namespace Benchs.Arrays;
[SimpleJob(RuntimeMoniker.Net60)]
[SimpleJob(RuntimeMoniker.NetCoreApp31)]
[SimpleJob(RuntimeMoniker.Net461)]
[MeanColumn]
public class ArrayRandomReadBenchmark
{
[Benchmark(Baseline = true)]
public int ArrayIndex()
{
var sum = 0;
foreach (var index in _indices)
{
sum += _array[index];
}
return sum;
}
[Benchmark]
public int BlackMagic()
{
var sum = 0;
ref var data = ref GetArrayDataReference(_array);
foreach (var index in _indices)
{
sum += Unsafe.Add(ref data, index);
}
return sum;
}
[Benchmark]
public int MemoryIndex()
{
var sum = 0;
foreach (var index in _indices)
{
sum += _memory.Span[index];
}
return sum;
}
[Benchmark]
public unsafe int UnsafeFixed()
{
var sum = 0;
foreach (var index in _indices)
{
fixed (int* arrayPtr = &_array[0])
{
sum += *(arrayPtr + index);
}
}
return sum;
}
[Benchmark]
public unsafe int UnsafePined()
{
var sum = 0;
foreach (var index in _indices)
{
sum += *((int*)_memoryHandle.Pointer + index);
}
return sum;
}
#region Configuration
private int[] _array = null!;
private ReadOnlyMemory<int> _memory;
private ReadOnlyMemory<int> _pinedMemory;
private MemoryHandle _memoryHandle;
private int[] _indices = null!;
[GlobalSetup]
public void Init()
{
const int count = 1021;
_array = new int[count];
_memory = new ReadOnlyMemory<int>(_array);
_pinedMemory = new ReadOnlyMemory<int>(_array);
_memoryHandle = _pinedMemory.Pin();
var rnd = new Random(1234);
for (var i = 0; i < count; i++)
{
_array[i] = rnd.Next(0, 10);
}
_indices = new int[count];
for (var i = 0; i < count; i++)
{
_indices[i] = rnd.Next(0, _array.Length - 1);
}
}
[GlobalCleanup]
public void Clear()
{
_memoryHandle.Dispose();
}
#endregion
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static ref T GetArrayDataReference<T>(T[] array) =>
ref Unsafe.As<byte, T>(ref Unsafe.As<RawArrayData>(array).Data);
[StructLayout(LayoutKind.Sequential)]
private sealed class RawArrayData
{
public IntPtr Length;
public byte Data;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment