Skip to content

Commit

Permalink
More baselines
Browse files Browse the repository at this point in the history
  • Loading branch information
benaadams committed Feb 27, 2018
1 parent 0ae26f9 commit 42af3a1
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 8 deletions.
53 changes: 45 additions & 8 deletions MemoryLookupBenchmark/MemoryAccessBenchmark.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Buffers.Current;
using System.Buffers.IMemoryList;
using System.Runtime.InteropServices;
using System.Buffers;

namespace MemoryLookupBenchmark
{
Expand All @@ -14,7 +15,12 @@ public class MemoryAccessBenchmark
public const long ItemCount = 0x3000_0000;
public const long ItemCountMask = ItemCount - 1;

private readonly MemoryMappedFileMemory _memory;
private readonly MemoryMappedFileMemory _mmMemory;

private readonly System.Buffers.ReadOnlySequenceSegment.ReadOnlySequence<byte> _singleReadOnlyBufferROSS;
private readonly System.Buffers.IMemoryList.ReadOnlySequence<byte> _singleRreadOnlyBufferIMemoryList;
private readonly System.Buffers.Current.ReadOnlySequence<byte> _singleReadOnlyBufferCurrent;

private readonly System.Buffers.ReadOnlySequenceSegment.ReadOnlySequence<byte> _readOnlyBufferROSS;
private readonly System.Buffers.IMemoryList.ReadOnlySequence<byte> _readOnlyBufferIMemoryList;
private readonly System.Buffers.Current.ReadOnlySequence<byte> _readOnlyBufferCurrent;
Expand All @@ -24,17 +30,20 @@ public class MemoryAccessBenchmark
public unsafe MemoryAccessBenchmark()
{
// Create a memory mapped file and fill it with random bytes
_memory = new MemoryMappedFileMemory(ItemLength * ItemCount);
GenerateRandomBytes(_memory.DataPointer, _memory.Length);
_readOnlyBufferROSS = _memory.CreateReadOnlyBufferROSS();
_readOnlyBufferIMemoryList = _memory.CreateReadOnlyBufferIMemoryList();
_readOnlyBufferCurrent = _memory.CreateReadOnlyBufferCurrent();
_mmMemory = new MemoryMappedFileMemory(ItemLength * ItemCount);
GenerateRandomBytes(_mmMemory.DataPointer, _mmMemory.Length);
_readOnlyBufferROSS = _mmMemory.CreateReadOnlyBufferROSS();
_readOnlyBufferIMemoryList = _mmMemory.CreateReadOnlyBufferIMemoryList();
_readOnlyBufferCurrent = _mmMemory.CreateReadOnlyBufferCurrent();

// Create the same RNG for both benchmarks
_random = XorShiftRandom.Create(0x6780867534);

// Allocate 5 bytes for the
_constantMemoryPointer = Marshal.AllocHGlobal(5);
_singleReadOnlyBufferROSS = ReadOnlySequenceSegment.OwnedMemorySegment<byte>.CreateSingleSequence(new PointerOwnedMemory<byte>((byte*)_constantMemoryPointer, 0, 5));
_readOnlyBufferIMemoryList = IMemoryList.OwnedMemorySegment<byte>.CreateSingleSequence(new PointerOwnedMemory<byte>((byte*)_constantMemoryPointer, 0, 5));
_readOnlyBufferCurrent = Current.OwnedMemorySegment<byte>.CreateSingleSequence(new PointerOwnedMemory<byte>((byte*)_constantMemoryPointer, 0, 5));
}

private static unsafe void GenerateRandomBytes(byte* pointer, long count)
Expand Down Expand Up @@ -72,18 +81,46 @@ public unsafe long NoRandomAccess()
return index;
}


[Benchmark(Description = "Random index, 1 segment. ReadOnlySequence<T> (current)")]
public unsafe long SingleSegmentCurrent()
{
Span<byte> destination = stackalloc byte[ItemLength];
long index = (long)(_random.Next() & ItemCountMask) * ItemLength;
_readOnlyBufferCurrent.Slice(0, ItemLength).CopyTo(destination);
return index;
}

[Benchmark(Description = "Random index, 1 segment. ReadOnlySequence<T> (PR dotnet/corefx#27455)")]
public unsafe long SingleSegmentIMemoryList()
{
Span<byte> destination = stackalloc byte[ItemLength];
long index = (long)(_random.Next() & ItemCountMask) * ItemLength;
_readOnlyBufferIMemoryList.Slice(0, ItemLength).CopyTo(destination);
return index;
}

[Benchmark(Description = "Random index, 1 segment. ReadOnlySequence<T> (PR dotnet/corefx#27499)")]
public unsafe long SingleSegmentROSS()
{
Span<byte> destination = stackalloc byte[ItemLength];
long index = (long)(_random.Next() & ItemCountMask) * ItemLength;
_readOnlyBufferROSS.Slice(0, ItemLength).CopyTo(destination);
return index;
}

[Benchmark(Baseline = true, Description = "MM item. Local Span")]
public unsafe void Direct()
{
Span<byte> destination = stackalloc byte[ItemLength];
new ReadOnlySpan<byte>(_memory.DataPointer + (long)(_random.Next() & ItemCountMask) * ItemLength, ItemLength).CopyTo(destination);
new ReadOnlySpan<byte>(_mmMemory.DataPointer + (long)(_random.Next() & ItemCountMask) * ItemLength, ItemLength).CopyTo(destination);
}

[Benchmark(Description = "MM item. BufferSlice<T>")]
public void Custom()
{
Span<byte> destination = stackalloc byte[ItemLength];
_memory.Slice((long)(_random.Next() & ItemCountMask) * ItemLength, ItemLength).Span.CopyTo(destination);
_mmMemory.Slice((long)(_random.Next() & ItemCountMask) * ItemLength, ItemLength).Span.CopyTo(destination);
}

[Benchmark(Description = "MM item. ReadOnlySequence<T> (current)")]
Expand Down
46 changes: 46 additions & 0 deletions MemoryLookupBenchmark/PointerOwnedMemory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System;
using System.Buffers;
using System.Buffers.Current;

namespace MemoryLookupBenchmark
{
public unsafe sealed class PointerOwnedMemory<T> : OwnedMemory<T>
{
private readonly byte* _pointer;
private readonly long _offset;
private readonly int _length;

public unsafe PointerOwnedMemory(byte* pointer, long offset, int length)
{
_pointer = pointer;
_offset = offset;
_length = length;
}

public override int Length => _length;

protected override void Dispose(bool disposing) { }

public override bool IsDisposed => false;
protected override bool IsRetained => true;

public override unsafe Span<T> Span => new Span<T>(_pointer + _offset, _length);

public override void Retain()
{
}

public override bool Release()
{
return false;
}

public override unsafe MemoryHandle Pin(int byteOffset = 0) => new MemoryHandle(this, _pointer + _offset);

protected override bool TryGetArray(out ArraySegment<T> arraySegment)
{
arraySegment = null;
return false;
}
}
}
7 changes: 7 additions & 0 deletions MemoryLookupBenchmark/corefxCurrent/SafeBufferOwnedMemory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ namespace MemoryLookupBenchmark.Current
/// <typeparam name="T"></typeparam>
public class OwnedMemorySegment<T> : IMemoryList<T>
{
public static ReadOnlySequence<T> CreateSingleSequence(OwnedMemory<T> buffer)
{
OwnedMemorySegment<T> first = new OwnedMemorySegment<T>(buffer);

return new ReadOnlySequence<T>(first, 0, first, first.Memory.Length);
}

private OwnedMemory<T> _ownedMemory;
public Memory<T> Memory { get; private set; }
public long RunningIndex { get; private set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ namespace MemoryLookupBenchmark.IMemoryList
/// <typeparam name="T"></typeparam>
public class OwnedMemorySegment<T> : IMemoryList<T>
{
public static ReadOnlySequence<T> CreateSingleSequence(OwnedMemory<T> buffer)
{
OwnedMemorySegment<T> first = new OwnedMemorySegment<T>(buffer);

return new ReadOnlySequence<T>(first, 0, first, first.Memory.Length);
}

private OwnedMemory<T> _ownedMemory;
public Memory<T> Memory { get; private set; }
public long RunningIndex { get; private set; }
Expand Down
7 changes: 7 additions & 0 deletions MemoryLookupBenchmark/corefxROSS/SafeBufferOwnedMemory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ namespace MemoryLookupBenchmark.ReadOnlySequenceSegment
/// <typeparam name="T"></typeparam>
public class OwnedMemorySegment<T> : ReadOnlySequenceSegment<T>
{
public static ReadOnlySequence<T> CreateSingleSequence(OwnedMemory<T> buffer)
{
OwnedMemorySegment<T> first = new OwnedMemorySegment<T>(buffer);

return new ReadOnlySequence<T>(first, 0, first, first.Memory.Length);
}

private OwnedMemory<T> _ownedMemory;

public OwnedMemorySegment(OwnedMemory<T> memory)
Expand Down

0 comments on commit 42af3a1

Please sign in to comment.