-
Notifications
You must be signed in to change notification settings - Fork 274
/
Copy pathSpan.cs
124 lines (98 loc) · 5.41 KB
/
Span.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections;
using System.Linq;
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Extensions;
using MicroBenchmarks;
namespace System.Memory
{
[GenericTypeArguments(typeof(byte))]
[GenericTypeArguments(typeof(char))]
[GenericTypeArguments(typeof(int))]
[BenchmarkCategory(Categories.Runtime, Categories.Libraries, Categories.Span)]
public class Span<T>
where T : struct, IComparable<T>, IEquatable<T>
{
[Params(
4, // non-vectorized code path
33, // both vectorized and non-vectorized code path
512)] // vectorized code path
public int Size;
private T[] _array, _same, _different, _emptyWithSingleValue;
private T[] _fourValues, _fiveValues;
private T _notDefaultValue;
[GlobalSetup]
public void Setup()
{
T[] array = ValuesGenerator.Array<T>(Size * 2);
_array = array.Take(Size).ToArray();
_same = _array.ToArray();
_different = array.Skip(Size).ToArray();
}
[Benchmark]
public void Clear() => new System.Span<T>(_array).Clear();
[Benchmark]
public void Fill() => new System.Span<T>(_array).Fill(default);
[Benchmark]
public void Reverse() => new System.Span<T>(_array).Reverse();
[Benchmark]
public T[] ToArray() => new System.Span<T>(_array).ToArray();
[Benchmark]
public bool SequenceEqual() => new System.Span<T>(_array).SequenceEqual(new System.ReadOnlySpan<T>(_same));
[Benchmark]
public int SequenceCompareTo() => new System.Span<T>(_array).SequenceCompareTo(new System.ReadOnlySpan<T>(_same));
[Benchmark]
public int SequenceCompareToDifferent() => new System.Span<T>(_array).SequenceCompareTo(new System.ReadOnlySpan<T>(_different));
[Benchmark]
public bool StartsWith() => new System.Span<T>(_array).StartsWith(new System.ReadOnlySpan<T>(_same).Slice(start: 0, length: Size / 2));
[Benchmark]
public bool EndsWith() => new System.Span<T>(_array).EndsWith(new System.ReadOnlySpan<T>(_same).Slice(start: Size / 2));
[GlobalSetup(Targets = new [] { nameof(IndexOfValue), nameof(LastIndexOfValue), nameof(LastIndexOfAnyValues),
nameof(IndexOfAnyTwoValues), nameof(IndexOfAnyThreeValues), nameof(IndexOfAnyFourValues), nameof(IndexOfAnyFiveValues) })]
public void SetupIndexOf()
{
_notDefaultValue = ValuesGenerator.GetNonDefaultValue<T>();
_fourValues = Enumerable.Repeat(_notDefaultValue, 4).ToArray();
_fiveValues = Enumerable.Repeat(_notDefaultValue, 5).ToArray();
_emptyWithSingleValue = new T[Size];
_emptyWithSingleValue[Size / 2] = _notDefaultValue;
}
[Benchmark]
public int IndexOfValue() => new System.Span<T>(_emptyWithSingleValue).IndexOf(_notDefaultValue);
[Benchmark]
public int IndexOfAnyTwoValues() => new System.Span<T>(_emptyWithSingleValue).IndexOfAny(_notDefaultValue, _notDefaultValue);
[Benchmark]
public int IndexOfAnyThreeValues() => new System.Span<T>(_emptyWithSingleValue).IndexOfAny(_notDefaultValue, _notDefaultValue, _notDefaultValue);
[Benchmark]
public int IndexOfAnyFourValues() => new System.Span<T>(_emptyWithSingleValue).IndexOfAny(new ReadOnlySpan<T>(_fourValues));
[Benchmark]
public int IndexOfAnyFiveValues() => new System.Span<T>(_emptyWithSingleValue).IndexOfAny(new ReadOnlySpan<T>(_fiveValues));
[Benchmark]
public int LastIndexOfValue() => new System.Span<T>(_emptyWithSingleValue).LastIndexOf(_notDefaultValue);
[Benchmark]
public int LastIndexOfAnyValues() => new System.Span<T>(_emptyWithSingleValue).LastIndexOfAny(_notDefaultValue, _notDefaultValue);
[GlobalSetup(Target = nameof(BinarySearch))]
public void SetupBinarySearch()
{
_notDefaultValue = ValuesGenerator.GetNonDefaultValue<T>();
_emptyWithSingleValue = new T[Size];
_emptyWithSingleValue[Size - 1] = _notDefaultValue;
}
[Benchmark]
public int BinarySearch() => new System.Span<T>(_emptyWithSingleValue).BinarySearch(_notDefaultValue);
[Benchmark(OperationsPerInvoke = 16)]
public void GetPinnableReference()
{
var span = new System.Span<T>(_array);
Consume(span.GetPinnableReference()); Consume(span.GetPinnableReference()); Consume(span.GetPinnableReference()); Consume(span.GetPinnableReference());
Consume(span.GetPinnableReference()); Consume(span.GetPinnableReference()); Consume(span.GetPinnableReference()); Consume(span.GetPinnableReference());
Consume(span.GetPinnableReference()); Consume(span.GetPinnableReference()); Consume(span.GetPinnableReference()); Consume(span.GetPinnableReference());
Consume(span.GetPinnableReference()); Consume(span.GetPinnableReference()); Consume(span.GetPinnableReference()); Consume(span.GetPinnableReference());
}
[MethodImpl(MethodImplOptions.NoInlining)]
private void Consume(in T _) { }
}
}