Skip to content

Commit

Permalink
implement Slice benchmarks
Browse files Browse the repository at this point in the history
  • Loading branch information
adamsitnik committed Jul 31, 2018
1 parent 9ba417e commit a822c76
Show file tree
Hide file tree
Showing 2 changed files with 172 additions and 3 deletions.
172 changes: 172 additions & 0 deletions src/benchmarks/corefx/System.Memory/Slice.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
using Benchmarks;

namespace System.Memory
{
[GenericTypeArguments(typeof(byte))]
[GenericTypeArguments(typeof(string))]
[BenchmarkCategory(Categories.CoreCLR, Categories.CoreFX, Categories.Span)]
public class Slice<T>
{
private const int Size = 10;

private T[] _nonEmptyArray = new T[Size];

[Benchmark(OperationsPerInvoke = 16)]
public System.Span<T> SpanStart()
{
System.Span<T> span, slice;
span = new System.Span<T>(_nonEmptyArray);

slice = span.Slice(Size / 2); Consume(in slice); slice = span.Slice(Size / 2); Consume(in slice);
slice = span.Slice(Size / 2); Consume(in slice); slice = span.Slice(Size / 2); Consume(in slice);
slice = span.Slice(Size / 2); Consume(in slice); slice = span.Slice(Size / 2); Consume(in slice);
slice = span.Slice(Size / 2); Consume(in slice); slice = span.Slice(Size / 2); Consume(in slice);
slice = span.Slice(Size / 2); Consume(in slice); slice = span.Slice(Size / 2); Consume(in slice);
slice = span.Slice(Size / 2); Consume(in slice); slice = span.Slice(Size / 2); Consume(in slice);
slice = span.Slice(Size / 2); Consume(in slice); slice = span.Slice(Size / 2); Consume(in slice);
slice = span.Slice(Size / 2); Consume(in slice); slice = span.Slice(Size / 2); Consume(in slice);

return slice;
}

[Benchmark(OperationsPerInvoke = 16)]
public System.Span<T> SpanStartLength()
{
System.Span<T> span, slice;
span = new System.Span<T>(_nonEmptyArray);

slice = span.Slice(Size / 2, 1); Consume(in slice); slice = span.Slice(Size / 2, 1); Consume(in slice);
slice = span.Slice(Size / 2, 1); Consume(in slice); slice = span.Slice(Size / 2, 1); Consume(in slice);
slice = span.Slice(Size / 2, 1); Consume(in slice); slice = span.Slice(Size / 2, 1); Consume(in slice);
slice = span.Slice(Size / 2, 1); Consume(in slice); slice = span.Slice(Size / 2, 1); Consume(in slice);
slice = span.Slice(Size / 2, 1); Consume(in slice); slice = span.Slice(Size / 2, 1); Consume(in slice);
slice = span.Slice(Size / 2, 1); Consume(in slice); slice = span.Slice(Size / 2, 1); Consume(in slice);
slice = span.Slice(Size / 2, 1); Consume(in slice); slice = span.Slice(Size / 2, 1); Consume(in slice);
slice = span.Slice(Size / 2, 1); Consume(in slice); slice = span.Slice(Size / 2, 1); Consume(in slice);

return slice;
}

[Benchmark(OperationsPerInvoke = 16)]
public System.ReadOnlySpan<T> ReadOnlySpanStart()
{
System.ReadOnlySpan<T> span, slice;
span = new System.ReadOnlySpan<T>(_nonEmptyArray);

slice = span.Slice(Size / 2); Consume(in slice); slice = span.Slice(Size / 2); Consume(in slice);
slice = span.Slice(Size / 2); Consume(in slice); slice = span.Slice(Size / 2); Consume(in slice);
slice = span.Slice(Size / 2); Consume(in slice); slice = span.Slice(Size / 2); Consume(in slice);
slice = span.Slice(Size / 2); Consume(in slice); slice = span.Slice(Size / 2); Consume(in slice);
slice = span.Slice(Size / 2); Consume(in slice); slice = span.Slice(Size / 2); Consume(in slice);
slice = span.Slice(Size / 2); Consume(in slice); slice = span.Slice(Size / 2); Consume(in slice);
slice = span.Slice(Size / 2); Consume(in slice); slice = span.Slice(Size / 2); Consume(in slice);
slice = span.Slice(Size / 2); Consume(in slice); slice = span.Slice(Size / 2); Consume(in slice);

return slice;
}

[Benchmark(OperationsPerInvoke = 16)]
public System.ReadOnlySpan<T> ReadOnlySpanStartLength()
{
System.ReadOnlySpan<T> span, slice;
span = new System.ReadOnlySpan<T>(_nonEmptyArray);

slice = span.Slice(Size / 2, 1); Consume(in slice); slice = span.Slice(Size / 2, 1); Consume(in slice);
slice = span.Slice(Size / 2, 1); Consume(in slice); slice = span.Slice(Size / 2, 1); Consume(in slice);
slice = span.Slice(Size / 2, 1); Consume(in slice); slice = span.Slice(Size / 2, 1); Consume(in slice);
slice = span.Slice(Size / 2, 1); Consume(in slice); slice = span.Slice(Size / 2, 1); Consume(in slice);
slice = span.Slice(Size / 2, 1); Consume(in slice); slice = span.Slice(Size / 2, 1); Consume(in slice);
slice = span.Slice(Size / 2, 1); Consume(in slice); slice = span.Slice(Size / 2, 1); Consume(in slice);
slice = span.Slice(Size / 2, 1); Consume(in slice); slice = span.Slice(Size / 2, 1); Consume(in slice);
slice = span.Slice(Size / 2, 1); Consume(in slice); slice = span.Slice(Size / 2, 1); Consume(in slice);

return slice;
}

[Benchmark(OperationsPerInvoke = 16)]
public System.Memory<T> MemoryStart()
{
System.Memory<T> memory, slice;
memory = new System.Memory<T>(_nonEmptyArray);

slice = memory.Slice(Size / 2); Consume(in slice); slice = memory.Slice(Size / 2); Consume(in slice);
slice = memory.Slice(Size / 2); Consume(in slice); slice = memory.Slice(Size / 2); Consume(in slice);
slice = memory.Slice(Size / 2); Consume(in slice); slice = memory.Slice(Size / 2); Consume(in slice);
slice = memory.Slice(Size / 2); Consume(in slice); slice = memory.Slice(Size / 2); Consume(in slice);
slice = memory.Slice(Size / 2); Consume(in slice); slice = memory.Slice(Size / 2); Consume(in slice);
slice = memory.Slice(Size / 2); Consume(in slice); slice = memory.Slice(Size / 2); Consume(in slice);
slice = memory.Slice(Size / 2); Consume(in slice); slice = memory.Slice(Size / 2); Consume(in slice);
slice = memory.Slice(Size / 2); Consume(in slice); slice = memory.Slice(Size / 2); Consume(in slice);

return slice;
}

[Benchmark(OperationsPerInvoke = 16)]
public System.Memory<T> MemoryStartLength()
{
System.Memory<T> memory, slice;
memory = new System.Memory<T>(_nonEmptyArray);

slice = memory.Slice(Size / 2, 1); Consume(in slice); slice = memory.Slice(Size / 2, 1); Consume(in slice);
slice = memory.Slice(Size / 2, 1); Consume(in slice); slice = memory.Slice(Size / 2, 1); Consume(in slice);
slice = memory.Slice(Size / 2, 1); Consume(in slice); slice = memory.Slice(Size / 2, 1); Consume(in slice);
slice = memory.Slice(Size / 2, 1); Consume(in slice); slice = memory.Slice(Size / 2, 1); Consume(in slice);
slice = memory.Slice(Size / 2, 1); Consume(in slice); slice = memory.Slice(Size / 2, 1); Consume(in slice);
slice = memory.Slice(Size / 2, 1); Consume(in slice); slice = memory.Slice(Size / 2, 1); Consume(in slice);
slice = memory.Slice(Size / 2, 1); Consume(in slice); slice = memory.Slice(Size / 2, 1); Consume(in slice);
slice = memory.Slice(Size / 2, 1); Consume(in slice); slice = memory.Slice(Size / 2, 1); Consume(in slice);

return slice;
}

[Benchmark(OperationsPerInvoke = 16)]
public System.ReadOnlyMemory<T> ReadOnlyMemoryStart()
{
System.ReadOnlyMemory<T> memory, slice;
memory = new System.ReadOnlyMemory<T>(_nonEmptyArray);

slice = memory.Slice(Size / 2); Consume(in slice); slice = memory.Slice(Size / 2); Consume(in slice);
slice = memory.Slice(Size / 2); Consume(in slice); slice = memory.Slice(Size / 2); Consume(in slice);
slice = memory.Slice(Size / 2); Consume(in slice); slice = memory.Slice(Size / 2); Consume(in slice);
slice = memory.Slice(Size / 2); Consume(in slice); slice = memory.Slice(Size / 2); Consume(in slice);
slice = memory.Slice(Size / 2); Consume(in slice); slice = memory.Slice(Size / 2); Consume(in slice);
slice = memory.Slice(Size / 2); Consume(in slice); slice = memory.Slice(Size / 2); Consume(in slice);
slice = memory.Slice(Size / 2); Consume(in slice); slice = memory.Slice(Size / 2); Consume(in slice);
slice = memory.Slice(Size / 2); Consume(in slice); slice = memory.Slice(Size / 2); Consume(in slice);

return slice;
}

[Benchmark(OperationsPerInvoke = 16)]
public System.ReadOnlyMemory<T> ReadOnlyMemoryStartLength()
{
System.ReadOnlyMemory<T> memory, slice;
memory = new System.ReadOnlyMemory<T>(_nonEmptyArray);

slice = memory.Slice(Size / 2, 1); Consume(in slice); slice = memory.Slice(Size / 2, 1); Consume(in slice);

This comment has been minimized.

Copy link
@jorive

jorive Jul 31, 2018

Member

Why is this manually unrolled? Can we use a loop instead?

This comment has been minimized.

Copy link
@jorive

jorive Jul 31, 2018

Member

*the same for the benchmarks above.

slice = memory.Slice(Size / 2, 1); Consume(in slice); slice = memory.Slice(Size / 2, 1); Consume(in slice);
slice = memory.Slice(Size / 2, 1); Consume(in slice); slice = memory.Slice(Size / 2, 1); Consume(in slice);
slice = memory.Slice(Size / 2, 1); Consume(in slice); slice = memory.Slice(Size / 2, 1); Consume(in slice);
slice = memory.Slice(Size / 2, 1); Consume(in slice); slice = memory.Slice(Size / 2, 1); Consume(in slice);
slice = memory.Slice(Size / 2, 1); Consume(in slice); slice = memory.Slice(Size / 2, 1); Consume(in slice);
slice = memory.Slice(Size / 2, 1); Consume(in slice); slice = memory.Slice(Size / 2, 1); Consume(in slice);
slice = memory.Slice(Size / 2, 1); Consume(in slice); slice = memory.Slice(Size / 2, 1); Consume(in slice);

return slice;
}

[MethodImpl(MethodImplOptions.NoInlining)]
private static void Consume(in System.Span<T> _) { }

[MethodImpl(MethodImplOptions.NoInlining)]
private static void Consume(in System.ReadOnlySpan<T> _) { }

[MethodImpl(MethodImplOptions.NoInlining)]
private static void Consume(in System.Memory<T> _) { }

[MethodImpl(MethodImplOptions.NoInlining)]
private static void Consume(in System.ReadOnlyMemory<T> _) { }
}
}
3 changes: 0 additions & 3 deletions src/benchmarks/corefx/System.Memory/Span.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@ public void Setup()
_same = _array.ToArray();
}

[Benchmark]
public System.Span<T> Slice() => new System.Span<T>(_array).Slice(Size / 2);

[Benchmark]
public void Clear() => new System.Span<T>(_array).Clear();

Expand Down

0 comments on commit a822c76

Please sign in to comment.