Last active
July 20, 2022 15:02
-
-
Save teoadal/e826cef1e5b2677fcaf1b23b3383a248 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
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