summaryrefslogtreecommitdiff
path: root/tests/src/JIT/Performance
diff options
context:
space:
mode:
authorAhson Ahmed Khan <ahsonkhan@users.noreply.github.com>2017-03-01 20:16:40 -0800
committerGitHub <noreply@github.com>2017-03-01 20:16:40 -0800
commit1bf3bbb44397875e94ae95b8527fd1928b5373fe (patch)
tree88852e14aa3609f999b5e302df50de73aafeabbc /tests/src/JIT/Performance
parent8597adf44830c451281ec42f0dbc2389e3395cfa (diff)
downloadcoreclr-1bf3bbb44397875e94ae95b8527fd1928b5373fe.tar.gz
coreclr-1bf3bbb44397875e94ae95b8527fd1928b5373fe.tar.bz2
coreclr-1bf3bbb44397875e94ae95b8527fd1928b5373fe.zip
Adding Span API perf tests for comparison with arrays and to monitor progress (#9790)
* wip * Adding Span API perf tests for comparison with arrays and to monitor progress * Reducing iteration count so tests finish in < 2 minutes * Reducing the number of test cases * Commenting out ref DangerousGetPinnableReference test * Updated csproj to use latest compiler * Tuning test cases and runtime
Diffstat (limited to 'tests/src/JIT/Performance')
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Span/SpanBench.cs1157
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Span/SpanBench.csproj2
2 files changed, 843 insertions, 316 deletions
diff --git a/tests/src/JIT/Performance/CodeQuality/Span/SpanBench.cs b/tests/src/JIT/Performance/CodeQuality/Span/SpanBench.cs
index 7ec2a4a088..b0358d2268 100644
--- a/tests/src/JIT/Performance/CodeQuality/Span/SpanBench.cs
+++ b/tests/src/JIT/Performance/CodeQuality/Span/SpanBench.cs
@@ -2,467 +2,992 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using Microsoft.Xunit.Performance;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Text;
using Xunit;
+using Microsoft.Xunit.Performance;
[assembly: OptimizeForBenchmarks]
[assembly: MeasureInstructionsRetired]
-class Tests
+namespace Span
{
+ public class SpanBench
+ {
#if DEBUG
- const int Iterations = 1;
+ const int BubbleSortIterations = 1;
+ const int QuickSortIterations = 1;
+ const int FillAllIterations = 1;
+ const int BaseIterations = 1;
#else
- const int Iterations = 10000;
+ const int BubbleSortIterations = 100;
+ const int QuickSortIterations = 1000;
+ const int FillAllIterations = 100000;
+ const int BaseIterations = 10000000;
#endif
- const int Size = 1024;
+ const int Size = 1024;
+ // Helpers
+ #region Helpers
+ [StructLayout(LayoutKind.Sequential)]
+ private sealed class TestClass<T>
+ {
+ private double _d;
+ public T[] C0;
+ }
- [MethodImpl(MethodImplOptions.NoInlining)]
- static void TestFillAllSpan(Span<byte> span)
- {
- for (int i = 0; i < span.Length; ++i) {
- span[i] = unchecked((byte)i);
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static void TestFillAllSpan(Span<byte> span)
+ {
+ for (int i = 0; i < span.Length; ++i) {
+ span[i] = unchecked((byte)i);
+ }
}
- }
- [MethodImpl(MethodImplOptions.NoInlining)]
- static void TestFillAllArray(byte[] data)
- {
- for (int i = 0; i < data.Length; ++i) {
- data[i] = unchecked((byte)i);
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static void TestFillAllArray(byte[] data)
+ {
+ for (int i = 0; i < data.Length; ++i) {
+ data[i] = unchecked((byte)i);
+ }
}
- }
- [MethodImpl(MethodImplOptions.NoInlining)]
- static void TestFillAllReverseSpan(Span<byte> span)
- {
- for (int i = span.Length; --i >= 0;) {
- span[i] = unchecked((byte)i);
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static void TestFillAllReverseSpan(Span<byte> span)
+ {
+ for (int i = span.Length; --i >= 0;) {
+ span[i] = unchecked((byte)i);
+ }
}
- }
- [MethodImpl(MethodImplOptions.NoInlining)]
- static void TestFillAllReverseArray(byte[] data)
- {
- for (int i = data.Length; --i >= 0;) {
- data[i] = unchecked((byte)i);
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static void TestFillAllReverseArray(byte[] data)
+ {
+ for (int i = data.Length; --i >= 0;) {
+ data[i] = unchecked((byte)i);
+ }
}
- }
- static int[] GetUnsortedData()
- {
- int[] unsortedData = new int[Size];
- Random r = new Random(42);
- for (int i = 0; i < unsortedData.Length; ++i)
+ static int[] GetUnsortedData()
{
- unsortedData[i] = r.Next();
+ int[] unsortedData = new int[Size];
+ Random r = new Random(42);
+ for (int i = 0; i < unsortedData.Length; ++i)
+ {
+ unsortedData[i] = r.Next();
+ }
+ return unsortedData;
}
- return unsortedData;
- }
- [MethodImpl(MethodImplOptions.NoInlining)]
- static void TestBubbleSortSpan(Span<int> span)
- {
- bool swap;
- int temp;
- int n = span.Length - 1;
- do {
- swap = false;
- for (int i = 0; i < n; i++) {
- if (span[i] > span[i + 1]) {
- temp = span[i];
- span[i] = span[i + 1];
- span[i + 1] = temp;
- swap = true;
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static void TestBubbleSortSpan(Span<int> span)
+ {
+ bool swap;
+ int temp;
+ int n = span.Length - 1;
+ do {
+ swap = false;
+ for (int i = 0; i < n; i++) {
+ if (span[i] > span[i + 1]) {
+ temp = span[i];
+ span[i] = span[i + 1];
+ span[i + 1] = temp;
+ swap = true;
+ }
}
+ --n;
}
- --n;
+ while (swap);
}
- while (swap);
- }
- [MethodImpl(MethodImplOptions.NoInlining)]
- static void TestBubbleSortArray(int[] data)
- {
- bool swap;
- int temp;
- int n = data.Length - 1;
- do {
- swap = false;
- for (int i = 0; i < n; i++) {
- if (data[i] > data[i + 1]) {
- temp = data[i];
- data[i] = data[i + 1];
- data[i + 1] = temp;
- swap = true;
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static void TestBubbleSortArray(int[] data)
+ {
+ bool swap;
+ int temp;
+ int n = data.Length - 1;
+ do {
+ swap = false;
+ for (int i = 0; i < n; i++) {
+ if (data[i] > data[i + 1]) {
+ temp = data[i];
+ data[i] = data[i + 1];
+ data[i + 1] = temp;
+ swap = true;
+ }
}
+ --n;
}
- --n;
+ while (swap);
}
- while (swap);
- }
- static void TestQuickSortSpan(Span<int> data)
- {
- QuickSortSpan(data);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- static void QuickSortSpan(Span<int> data)
- {
- if (data.Length <= 1) {
- return;
+ static void TestQuickSortSpan(Span<int> data)
+ {
+ QuickSortSpan(data);
}
- int lo = 0;
- int hi = data.Length - 1;
- int i, j;
- int pivot, temp;
- for (i = lo, j = hi, pivot = data[hi]; i < j;) {
- while (i < j && data[i] <= pivot) {
- ++i;
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static void QuickSortSpan(Span<int> data)
+ {
+ if (data.Length <= 1) {
+ return;
}
- while (j > i && data[j] >= pivot) {
- --j;
+
+ int lo = 0;
+ int hi = data.Length - 1;
+ int i, j;
+ int pivot, temp;
+ for (i = lo, j = hi, pivot = data[hi]; i < j;) {
+ while (i < j && data[i] <= pivot) {
+ ++i;
+ }
+ while (j > i && data[j] >= pivot) {
+ --j;
+ }
+ if (i < j) {
+ temp = data[i];
+ data[i] = data[j];
+ data[j] = temp;
+ }
}
- if (i < j) {
+ if (i != hi) {
temp = data[i];
- data[i] = data[j];
- data[j] = temp;
+ data[i] = pivot;
+ data[hi] = temp;
}
- }
- if (i != hi) {
- temp = data[i];
- data[i] = pivot;
- data[hi] = temp;
- }
-
- QuickSortSpan(data.Slice(0, i));
- QuickSortSpan(data.Slice(i + 1));
- }
- static void TestQuickSortArray(int[] data)
- {
- QuickSortArray(data, 0, data.Length - 1);
- }
+ QuickSortSpan(data.Slice(0, i));
+ QuickSortSpan(data.Slice(i + 1));
+ }
- [MethodImpl(MethodImplOptions.NoInlining)]
- static void QuickSortArray(int[] data, int lo, int hi)
- {
- if (lo >= hi) {
- return;
+ static void TestQuickSortArray(int[] data)
+ {
+ QuickSortArray(data, 0, data.Length - 1);
}
- int i, j;
- int pivot, temp;
- for (i = lo, j = hi, pivot = data[hi]; i < j;) {
- while (i < j && data[i] <= pivot) {
- ++i;
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static void QuickSortArray(int[] data, int lo, int hi)
+ {
+ if (lo >= hi) {
+ return;
}
- while (j > i && data[j] >= pivot) {
- --j;
+
+ int i, j;
+ int pivot, temp;
+ for (i = lo, j = hi, pivot = data[hi]; i < j;) {
+ while (i < j && data[i] <= pivot) {
+ ++i;
+ }
+ while (j > i && data[j] >= pivot) {
+ --j;
+ }
+ if (i < j) {
+ temp = data[i];
+ data[i] = data[j];
+ data[j] = temp;
+ }
}
- if (i < j) {
+ if (i != hi) {
temp = data[i];
- data[i] = data[j];
- data[j] = temp;
+ data[i] = pivot;
+ data[hi] = temp;
}
- }
- if (i != hi) {
- temp = data[i];
- data[i] = pivot;
- data[hi] = temp;
- }
- QuickSortArray(data, lo, i - 1);
- QuickSortArray(data, i + 1, hi);
- }
-
- // XUNIT-PERF tests
+ QuickSortArray(data, lo, i - 1);
+ QuickSortArray(data, i + 1, hi);
+ }
+ #endregion
- [Benchmark]
- public static void FillAllSpan()
- {
- byte[] a = new byte[Size];
- Span<byte> s = new Span<byte>(a);
- foreach (var iteration in Benchmark.Iterations)
+ // XUNIT-PERF tests
+ #region XUNIT-PERF tests
+ [Benchmark]
+ public static void FillAllSpan()
{
- using (iteration.StartMeasurement())
+ byte[] a = new byte[Size];
+ Span<byte> s = new Span<byte>(a);
+ foreach (var iteration in Benchmark.Iterations)
{
- for (int i = 0; i < Iterations; i++)
+ using (iteration.StartMeasurement())
{
- TestFillAllSpan(s);
+ for (int i = 0; i < FillAllIterations; i++)
+ {
+ TestFillAllSpan(s);
+ }
}
}
}
- }
- [Benchmark]
- public static void FillAllArray()
- {
- byte[] a = new byte[Size];
- foreach (var iteration in Benchmark.Iterations)
+ [Benchmark]
+ public static void FillAllArray()
{
- using (iteration.StartMeasurement())
+ byte[] a = new byte[Size];
+ foreach (var iteration in Benchmark.Iterations)
{
- for (int i = 0; i < Iterations; i++)
+ using (iteration.StartMeasurement())
{
- TestFillAllArray(a);
+ for (int i = 0; i < FillAllIterations; i++)
+ {
+ TestFillAllArray(a);
+ }
}
}
}
- }
- [Benchmark]
- public static void FillAllReverseSpan()
- {
- byte[] a = new byte[Size];
- Span<byte> s = new Span<byte>(a);
- foreach (var iteration in Benchmark.Iterations)
+ [Benchmark]
+ public static void FillAllReverseSpan()
{
- using (iteration.StartMeasurement())
+ byte[] a = new byte[Size];
+ Span<byte> s = new Span<byte>(a);
+ foreach (var iteration in Benchmark.Iterations)
{
- for (int i = 0; i < Iterations; i++)
+ using (iteration.StartMeasurement())
{
- TestFillAllReverseSpan(s);
+ for (int i = 0; i < FillAllIterations; i++)
+ {
+ TestFillAllReverseSpan(s);
+ }
}
}
}
- }
- [Benchmark]
- public static void FillAllReverseArray()
- {
- byte[] a = new byte[Size];
- foreach (var iteration in Benchmark.Iterations)
+ [Benchmark]
+ public static void FillAllReverseArray()
{
- using (iteration.StartMeasurement())
+ byte[] a = new byte[Size];
+ foreach (var iteration in Benchmark.Iterations)
{
- for (int i = 0; i < Iterations; i++)
+ using (iteration.StartMeasurement())
{
- TestFillAllReverseArray(a);
+ for (int i = 0; i < FillAllIterations; i++)
+ {
+ TestFillAllReverseArray(a);
+ }
}
}
}
- }
-
- [Benchmark]
- public static void QuickSortSpan()
- {
- int[] data = new int[Size];
- int[] unsortedData = GetUnsortedData();
- Span<int> span = new Span<int>(data);
- foreach (var iteration in Benchmark.Iterations)
+ [Benchmark]
+ public static void QuickSortSpan()
{
- using (iteration.StartMeasurement())
+ int[] data = new int[Size];
+ int[] unsortedData = GetUnsortedData();
+ Span<int> span = new Span<int>(data);
+
+ foreach (var iteration in Benchmark.Iterations)
{
- for (int i = 0; i < Iterations; i++)
+ using (iteration.StartMeasurement())
{
- Array.Copy(unsortedData, data, Size);
- TestQuickSortSpan(span);
+ for (int i = 0; i < QuickSortIterations; i++)
+ {
+ Array.Copy(unsortedData, data, Size);
+ TestQuickSortSpan(span);
+ }
}
}
}
- }
-
- [Benchmark]
- public static void BubbleSortSpan()
- {
- int[] data = new int[Size];
- int[] unsortedData = GetUnsortedData();
- Span<int> span = new Span<int>(data);
- foreach (var iteration in Benchmark.Iterations)
+ [Benchmark]
+ public static void BubbleSortSpan()
{
- using (iteration.StartMeasurement())
+ int[] data = new int[Size];
+ int[] unsortedData = GetUnsortedData();
+ Span<int> span = new Span<int>(data);
+
+ foreach (var iteration in Benchmark.Iterations)
{
- for (int i = 0; i < Iterations; i++)
+ using (iteration.StartMeasurement())
{
- Array.Copy(unsortedData, data, Size);
- TestBubbleSortSpan(span);
+ for (int i = 0; i < BubbleSortIterations; i++)
+ {
+ Array.Copy(unsortedData, data, Size);
+ TestBubbleSortSpan(span);
+ }
}
}
}
- }
- [Benchmark]
- public static void QuickSortArray()
- {
- int[] data = new int[Size];
- int[] unsortedData = GetUnsortedData();
-
- foreach (var iteration in Benchmark.Iterations)
+ [Benchmark]
+ public static void QuickSortArray()
{
- using (iteration.StartMeasurement())
+ int[] data = new int[Size];
+ int[] unsortedData = GetUnsortedData();
+
+ foreach (var iteration in Benchmark.Iterations)
{
- for (int i = 0; i < Iterations; i++)
+ using (iteration.StartMeasurement())
{
- Array.Copy(unsortedData, data, Size);
- TestQuickSortArray(data);
+ for (int i = 0; i < QuickSortIterations; i++)
+ {
+ Array.Copy(unsortedData, data, Size);
+ TestQuickSortArray(data);
+ }
}
}
}
- }
- [Benchmark]
- public static void BubbleSortArray()
- {
- int[] data = new int[Size];
- int[] unsortedData = GetUnsortedData();
-
- foreach (var iteration in Benchmark.Iterations)
+ [Benchmark]
+ public static void BubbleSortArray()
{
- using (iteration.StartMeasurement())
+ int[] data = new int[Size];
+ int[] unsortedData = GetUnsortedData();
+
+ foreach (var iteration in Benchmark.Iterations)
{
- for (int i = 0; i < Iterations; i++)
+ using (iteration.StartMeasurement())
{
- Array.Copy(unsortedData, data, Size);
- TestBubbleSortArray(data);
+ for (int i = 0; i < BubbleSortIterations; i++)
+ {
+ Array.Copy(unsortedData, data, Size);
+ TestBubbleSortArray(data);
+ }
}
}
}
- }
+ #endregion
+
+ // TestSpanAPIs (For comparison with Array and Slow Span)
+ #region TestSpanAPIs
+
+ #region TestSpanConstructor<T>
+ [Benchmark(InnerIterationCount = BaseIterations)]
+ [InlineData(1)]
+ [InlineData(10)]
+ [InlineData(100)]
+ [InlineData(1000)]
+ public static void TestSpanConstructorByte(int length)
+ {
+ var array = new byte[length];
+ Span<byte> span;
+ foreach (var iteration in Benchmark.Iterations)
+ using (iteration.StartMeasurement())
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ span = new Span<byte>(array);
+ }
- // EXE-based testing
+ [Benchmark(InnerIterationCount = BaseIterations / 100)]
+ [InlineData(1)]
+ [InlineData(10)]
+ [InlineData(100)]
+ [InlineData(1000)]
+ public static void TestSpanConstructorString(int length)
+ {
+ var array = new string[length];
+ Span<string> span;
+ foreach (var iteration in Benchmark.Iterations)
+ using (iteration.StartMeasurement())
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ span = new Span<string>(array);
+ }
+ #endregion
+
+ #region TestSpanDangerousCreate<T>
+ [Benchmark(InnerIterationCount = BaseIterations)]
+ [InlineData(1)]
+ [InlineData(10)]
+ [InlineData(100)]
+ [InlineData(1000)]
+ public static void TestSpanDangerousCreateByte(int length)
+ {
+ TestClass<byte> testClass = new TestClass<byte>();
+ testClass.C0 = new byte[length];
+ Span<byte> span;
+ foreach (var iteration in Benchmark.Iterations)
+ using (iteration.StartMeasurement())
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ span = Span<byte>.DangerousCreate(testClass, ref testClass.C0[0], testClass.C0.Length);
+ }
- static void FillAllSpanBase()
- {
- byte[] a = new byte[Size];
- Span<byte> s = new Span<byte>(a);
- for (int i = 0; i < Iterations; i++)
+ [Benchmark(InnerIterationCount = BaseIterations)]
+ [InlineData(1)]
+ [InlineData(10)]
+ [InlineData(100)]
+ [InlineData(1000)]
+ public static void TestSpanDangerousCreateString(int length)
{
- TestFillAllSpan(s);
+ TestClass<string> testClass = new TestClass<string>();
+ testClass.C0 = new string[length];
+ Span<string> span;
+ foreach (var iteration in Benchmark.Iterations)
+ using (iteration.StartMeasurement())
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ span = Span<string>.DangerousCreate(testClass, ref testClass.C0[0], testClass.C0.Length);
+ }
+ #endregion
+
+ #region TestSpanDangerousGetPinnableReference<T>
+ [Benchmark(InnerIterationCount = BaseIterations)]
+ [InlineData(1)]
+ [InlineData(10)]
+ [InlineData(100)]
+ [InlineData(1000)]
+ public static void TestSpanDangerousGetPinnableReferenceByte(int length)
+ {
+ var array = new byte[length];
+ var span = new Span<byte>(array);
+ foreach (var iteration in Benchmark.Iterations)
+ using (iteration.StartMeasurement())
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ref byte temp = ref span.DangerousGetPinnableReference();
+ }
}
- }
- static void FillAllArrayBase()
- {
- byte[] a = new byte[Size];
- for (int i = 0; i < Iterations; i++)
+ [Benchmark(InnerIterationCount = BaseIterations)]
+ [InlineData(1)]
+ [InlineData(10)]
+ [InlineData(100)]
+ [InlineData(1000)]
+ public static void TestSpanDangerousGetPinnableReferenceString(int length)
{
- TestFillAllArray(a);
+ var array = new string[length];
+ var span = new Span<string>(array);
+ foreach (var iteration in Benchmark.Iterations)
+ using (iteration.StartMeasurement())
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ref string temp = ref span.DangerousGetPinnableReference();
+ }
}
- }
+ #endregion
+
+ #region TestSpanIndex<T>
+ [Benchmark(InnerIterationCount = BaseIterations)]
+ [InlineData(1)]
+ [InlineData(10)]
+ [InlineData(100)]
+ [InlineData(1000)]
+ public static void TestSpanIndexByte(int length)
+ {
+ var array = new byte[length];
+ var span = new Span<byte>(array);
+ byte temp;
+ foreach (var iteration in Benchmark.Iterations)
+ using (iteration.StartMeasurement())
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ temp = span[length/2];
- static void FillAllReverseSpanBase()
- {
- byte[] a = new byte[Size];
- Span<byte> s = new Span<byte>(a);
- for (int i = 0; i < Iterations; i++)
+ }
+
+ [Benchmark(InnerIterationCount = BaseIterations)]
+ [InlineData(1)]
+ [InlineData(10)]
+ [InlineData(100)]
+ [InlineData(1000)]
+ public static void TestSpanIndexString(int length)
{
- TestFillAllReverseSpan(s);
+ var array = new string[length];
+ var span = new Span<string>(array);
+ string temp;
+ foreach (var iteration in Benchmark.Iterations)
+ using (iteration.StartMeasurement())
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ temp = span[length / 2];
}
- }
+ #endregion
+
+ #region TestArrayIndex<T>
+ [Benchmark(InnerIterationCount = BaseIterations)]
+ [InlineData(1)]
+ [InlineData(10)]
+ [InlineData(100)]
+ [InlineData(1000)]
+ public static void TestArrayIndexByte(int length)
+ {
+ var array = new byte[length];
+ byte temp;
+ foreach (var iteration in Benchmark.Iterations)
+ using (iteration.StartMeasurement())
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ temp = array[length / 2];
- static void FillAllReverseArrayBase()
- {
- byte[] a = new byte[Size];
- for (int i = 0; i < Iterations; i++)
+ }
+
+ [Benchmark(InnerIterationCount = BaseIterations)]
+ [InlineData(1)]
+ [InlineData(10)]
+ [InlineData(100)]
+ [InlineData(1000)]
+ public static void TestArrayIndexString(int length)
{
- TestFillAllReverseArray(a);
+ var array = new string[length];
+ string temp;
+ foreach (var iteration in Benchmark.Iterations)
+ using (iteration.StartMeasurement())
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ temp = array[length / 2];
+ }
+ #endregion
+
+ #region TestSpanSlice<T>
+ [Benchmark(InnerIterationCount = BaseIterations)]
+ [InlineData(1)]
+ [InlineData(10)]
+ [InlineData(100)]
+ [InlineData(1000)]
+ public static void TestSpanSliceByte(int length)
+ {
+ var array = new byte[length];
+ var span = new Span<byte>(array);
+ Span<byte> temp;
+ foreach (var iteration in Benchmark.Iterations)
+ using (iteration.StartMeasurement())
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ temp = span.Slice(length / 2);
}
- }
- static void QuickSortSpanBase()
- {
- int[] data = new int[Size];
- int[] unsortedData = GetUnsortedData();
- Span<int> span = new Span<int>(data);
+ [Benchmark(InnerIterationCount = BaseIterations)]
+ [InlineData(1)]
+ [InlineData(10)]
+ [InlineData(100)]
+ [InlineData(1000)]
+ public static void TestSpanSliceString(int length)
+ {
+ var array = new string[length];
+ var span = new Span<string>(array);
+ Span<string> temp;
+ foreach (var iteration in Benchmark.Iterations)
+ using (iteration.StartMeasurement())
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ temp = span.Slice(length / 2);
+ }
+ #endregion
+
+ #region TestSpanToArray<T>
+ [Benchmark(InnerIterationCount = BaseIterations / 100)]
+ [InlineData(1)]
+ [InlineData(10)]
+ [InlineData(100)]
+ [InlineData(1000)]
+ public static void TestSpanToArrayByte(int length)
+ {
+ var array = new byte[length];
+ var span = new Span<byte>(array);
+ byte[] temp;
+ foreach (var iteration in Benchmark.Iterations)
+ using (iteration.StartMeasurement())
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ temp = span.ToArray();
+ }
- for (int i = 0; i < Iterations; i++)
+ [Benchmark(InnerIterationCount = BaseIterations / 100)]
+ [InlineData(1)]
+ [InlineData(10)]
+ [InlineData(100)]
+ [InlineData(1000)]
+ public static void TestSpanToArrayString(int length)
{
- Array.Copy(unsortedData, data, Size);
- TestQuickSortSpan(span);
+ var array = new string[length];
+ var span = new Span<string>(array);
+ string[] temp;
+ foreach (var iteration in Benchmark.Iterations)
+ using (iteration.StartMeasurement())
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ temp = span.ToArray();
+ }
+ #endregion
+
+ #region TestSpanCopyTo<T>
+ [Benchmark(InnerIterationCount = BaseIterations / 10)]
+ [InlineData(1)]
+ [InlineData(10)]
+ [InlineData(100)]
+ [InlineData(1000)]
+ public static void TestSpanCopyToByte(int length)
+ {
+ var array = new byte[length];
+ var span = new Span<byte>(array);
+ var destArray = new byte[array.Length];
+ var destination = new Span<byte>(destArray);
+ foreach (var iteration in Benchmark.Iterations)
+ using (iteration.StartMeasurement())
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ span.CopyTo(destination);
}
- }
- static void BubbleSortSpanBase()
- {
- int[] data = new int[Size];
- int[] unsortedData = GetUnsortedData();
- Span<int> span = new Span<int>(data);
+ [Benchmark(InnerIterationCount = BaseIterations / 100)]
+ [InlineData(1)]
+ [InlineData(10)]
+ [InlineData(100)]
+ [InlineData(1000)]
+ public static void TestSpanCopyToString(int length)
+ {
+ var array = new string[length];
+ var span = new Span<string>(array);
+ var destArray = new string[array.Length];
+ var destination = new Span<string>(destArray);
+ foreach (var iteration in Benchmark.Iterations)
+ using (iteration.StartMeasurement())
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ span.CopyTo(destination);
+ }
+ #endregion
+
+ #region TestArrayCopyTo<T>
+ [Benchmark(InnerIterationCount = BaseIterations / 10)]
+ [InlineData(1)]
+ [InlineData(10)]
+ [InlineData(100)]
+ [InlineData(1000)]
+ public static void TestArrayCopyToByte(int length)
+ {
+ var array = new byte[length];
+ var destination = new byte[array.Length];
+ foreach (var iteration in Benchmark.Iterations)
+ using (iteration.StartMeasurement())
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ array.CopyTo(destination, 0);
+ }
- for (int i = 0; i < Iterations; i++)
+ [Benchmark(InnerIterationCount = BaseIterations / 100)]
+ [InlineData(1)]
+ [InlineData(10)]
+ [InlineData(100)]
+ [InlineData(1000)]
+ public static void TestArrayCopyToString(int length)
{
- Array.Copy(unsortedData, data, Size);
- TestBubbleSortSpan(span);
+ var array = new string[length];
+ var destination = new string[array.Length];
+ foreach (var iteration in Benchmark.Iterations)
+ using (iteration.StartMeasurement())
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ array.CopyTo(destination, 0);
+ }
+ #endregion
+
+ #region TestSpanFill<T>
+ [Benchmark(InnerIterationCount = BaseIterations * 10)]
+ [InlineData(1)]
+ [InlineData(10)]
+ [InlineData(100)]
+ [InlineData(1000)]
+ public static void TestSpanFillByte(int length)
+ {
+ var array = new byte[length];
+ var span = new Span<byte>(array);
+ foreach (var iteration in Benchmark.Iterations)
+ using (iteration.StartMeasurement())
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ span.Fill(default(byte));
}
- }
- static void QuickSortArrayBase()
- {
- int[] data = new int[Size];
- int[] unsortedData = GetUnsortedData();
+ [Benchmark(InnerIterationCount = BaseIterations / 100)]
+ [InlineData(1)]
+ [InlineData(10)]
+ [InlineData(100)]
+ [InlineData(1000)]
+ public static void TestSpanFillString(int length)
+ {
+ var array = new string[length];
+ var span = new Span<string>(array);
+ foreach (var iteration in Benchmark.Iterations)
+ using (iteration.StartMeasurement())
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ span.Fill(default(string));
+ }
+ #endregion
+
+ #region TestSpanClear<T>
+ [Benchmark(InnerIterationCount = BaseIterations / 10)]
+ [InlineData(1)]
+ [InlineData(10)]
+ [InlineData(100)]
+ [InlineData(1000)]
+ public static void TestSpanClearByte(int length)
+ {
+ var array = new byte[length];
+ var span = new Span<byte>(array);
+ foreach (var iteration in Benchmark.Iterations)
+ using (iteration.StartMeasurement())
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ span.Clear();
+ }
- for (int i = 0; i < Iterations; i++)
+ [Benchmark(InnerIterationCount = BaseIterations / 10)]
+ [InlineData(1)]
+ [InlineData(10)]
+ [InlineData(100)]
+ [InlineData(1000)]
+ public static void TestSpanClearString(int length)
{
- Array.Copy(unsortedData, data, Size);
- TestQuickSortArray(data);
+ var array = new string[length];
+ var span = new Span<string>(array);
+ foreach (var iteration in Benchmark.Iterations)
+ using (iteration.StartMeasurement())
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ span.Clear();
+ }
+ #endregion
+
+ #region TestArrayClear<T>
+ [Benchmark(InnerIterationCount = BaseIterations / 10)]
+ [InlineData(1)]
+ [InlineData(10)]
+ [InlineData(100)]
+ [InlineData(1000)]
+ public static void TestArrayClearByte(int length)
+ {
+ var array = new byte[length];
+ foreach (var iteration in Benchmark.Iterations)
+ using (iteration.StartMeasurement())
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ Array.Clear(array, 0, length);
}
- }
- static void BubbleSortArrayBase()
- {
- int[] data = new int[Size];
- int[] unsortedData = GetUnsortedData();
+ [Benchmark(InnerIterationCount = BaseIterations / 10)]
+ [InlineData(1)]
+ [InlineData(10)]
+ [InlineData(100)]
+ [InlineData(1000)]
+ public static void TestArrayClearString(int length)
+ {
+ var array = new string[length];
+ foreach (var iteration in Benchmark.Iterations)
+ using (iteration.StartMeasurement())
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ Array.Clear(array, 0, length);
+ }
+ #endregion
+
+ #region TestSpanAsBytes<T>
+ [Benchmark(InnerIterationCount = BaseIterations)]
+ [InlineData(1)]
+ [InlineData(10)]
+ [InlineData(100)]
+ [InlineData(1000)]
+ public static void TestSpanAsBytesByte(int length)
+ {
+ var array = new byte[length];
+ var span = new Span<byte>(array);
+ foreach (var iteration in Benchmark.Iterations)
+ using (iteration.StartMeasurement())
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ Span<byte> temp = span.AsBytes<byte>();
+ }
+ }
- for (int i = 0; i < Iterations; i++)
+ [Benchmark(InnerIterationCount = BaseIterations)]
+ [InlineData(1)]
+ [InlineData(10)]
+ [InlineData(100)]
+ [InlineData(1000)]
+ public static void TestSpanAsBytesInt(int length)
{
- Array.Copy(unsortedData, data, Size);
- TestBubbleSortArray(data);
+ var array = new int[length];
+ var span = new Span<int>(array);
+ foreach (var iteration in Benchmark.Iterations)
+ using (iteration.StartMeasurement())
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ Span<byte> temp = span.AsBytes<int>();
+ }
+ }
+ #endregion
+
+ #region TestSpanNonPortableCast<T>
+ [Benchmark(InnerIterationCount = BaseIterations)]
+ [InlineData(1)]
+ [InlineData(10)]
+ [InlineData(100)]
+ [InlineData(1000)]
+ public static void TestSpanNonPortableCastFromByteToInt(int length)
+ {
+ var array = new byte[length];
+ var span = new Span<byte>(array);
+ foreach (var iteration in Benchmark.Iterations)
+ using (iteration.StartMeasurement())
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ Span<int> temp = span.NonPortableCast<byte, int>();
+ }
}
- }
- static double Bench(Action f)
- {
- Stopwatch sw = Stopwatch.StartNew();
- f();
- sw.Stop();
- return sw.Elapsed.TotalMilliseconds;
- }
+ [Benchmark(InnerIterationCount = BaseIterations)]
+ [InlineData(1)]
+ [InlineData(10)]
+ [InlineData(100)]
+ [InlineData(1000)]
+ public static void TestSpanNonPortableCastFromIntToByte(int length)
+ {
+ var array = new int[length];
+ var span = new Span<int>(array);
+ foreach (var iteration in Benchmark.Iterations)
+ using (iteration.StartMeasurement())
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ Span<byte> temp = span.NonPortableCast<int, byte>();
+ }
+ }
+ #endregion
+
+ #region TestSpanSliceStringChar<T>
+ [Benchmark(InnerIterationCount = BaseIterations)]
+ [InlineData(1)]
+ [InlineData(10)]
+ [InlineData(100)]
+ [InlineData(1000)]
+ public static void TestSpanSliceStringChar(int length)
+ {
+ StringBuilder sb = new StringBuilder();
+ Random rand = new Random(42);
+ char[] c = new char[1];
+ for (int i = 0; i < length; i++)
+ {
+ c[0] = (char)rand.Next(32, 126);
+ sb.Append(new string(c));
+ }
+ string s = sb.ToString();
+
+ foreach (var iteration in Benchmark.Iterations)
+ using (iteration.StartMeasurement())
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlySpan<char> temp = s.Slice();
+ }
+ }
+ #endregion
- static IEnumerable<object[]> MakeArgs(params string[] args)
- {
- return args.Select(arg => new object[] { arg });
- }
+ #endregion
+
+ // EXE-based testing
+ #region EXE-base testing
+ static void FillAllSpanBase()
+ {
+ byte[] a = new byte[Size];
+ Span<byte> s = new Span<byte>(a);
+ for (int i = 0; i < FillAllIterations; i++)
+ {
+ TestFillAllSpan(s);
+ }
+ }
- static IEnumerable<object[]> TestFuncs = MakeArgs(
- "FillAllSpanBase", "FillAllArrayBase",
- "FillAllReverseSpanBase", "FillAllReverseArrayBase",
- "BubbleSortSpanBase", "BubbleSortArrayBase",
- "QuickSortSpanBase", "QuickSortArrayBase"
- );
+ static void FillAllArrayBase()
+ {
+ byte[] a = new byte[Size];
+ for (int i = 0; i < FillAllIterations; i++)
+ {
+ TestFillAllArray(a);
+ }
+ }
- static Action LookupFunc(object o)
- {
- TypeInfo t = typeof(Tests).GetTypeInfo();
- MethodInfo m = t.GetDeclaredMethod((string) o);
- return m.CreateDelegate(typeof(Action)) as Action;
- }
+ static void FillAllReverseSpanBase()
+ {
+ byte[] a = new byte[Size];
+ Span<byte> s = new Span<byte>(a);
+ for (int i = 0; i < FillAllIterations; i++)
+ {
+ TestFillAllReverseSpan(s);
+ }
+ }
- public static int Main(string[] args)
- {
- bool result = true;
+ static void FillAllReverseArrayBase()
+ {
+ byte[] a = new byte[Size];
+ for (int i = 0; i < FillAllIterations; i++)
+ {
+ TestFillAllReverseArray(a);
+ }
+ }
- foreach(object[] o in TestFuncs)
+ static void QuickSortSpanBase()
{
- string funcName = (string) o[0];
- Action func = LookupFunc(funcName);
- double timeInMs = Bench(func);
- Console.WriteLine("{0}: {1}ms", funcName, timeInMs);
+ int[] data = new int[Size];
+ int[] unsortedData = GetUnsortedData();
+ Span<int> span = new Span<int>(data);
+
+ for (int i = 0; i < QuickSortIterations; i++)
+ {
+ Array.Copy(unsortedData, data, Size);
+ TestQuickSortSpan(span);
+ }
}
- return (result ? 100 : -1);
- }
-}
+ static void BubbleSortSpanBase()
+ {
+ int[] data = new int[Size];
+ int[] unsortedData = GetUnsortedData();
+ Span<int> span = new Span<int>(data);
+
+ for (int i = 0; i < BubbleSortIterations; i++)
+ {
+ Array.Copy(unsortedData, data, Size);
+ TestBubbleSortSpan(span);
+ }
+ }
+
+ static void QuickSortArrayBase()
+ {
+ int[] data = new int[Size];
+ int[] unsortedData = GetUnsortedData();
+ for (int i = 0; i < QuickSortIterations; i++)
+ {
+ Array.Copy(unsortedData, data, Size);
+ TestQuickSortArray(data);
+ }
+ }
+
+ static void BubbleSortArrayBase()
+ {
+ int[] data = new int[Size];
+ int[] unsortedData = GetUnsortedData();
+
+ for (int i = 0; i < BubbleSortIterations; i++)
+ {
+ Array.Copy(unsortedData, data, Size);
+ TestBubbleSortArray(data);
+ }
+ }
+ #endregion
+
+ static double Bench(Action f)
+ {
+ Stopwatch sw = Stopwatch.StartNew();
+ f();
+ sw.Stop();
+ return sw.Elapsed.TotalMilliseconds;
+ }
+
+ static IEnumerable<object[]> MakeArgs(params string[] args)
+ {
+ return args.Select(arg => new object[] { arg });
+ }
+
+ static IEnumerable<object[]> TestFuncs = MakeArgs(
+ "FillAllSpanBase", "FillAllArrayBase",
+ "FillAllReverseSpanBase", "FillAllReverseArrayBase",
+ "BubbleSortSpanBase", "BubbleSortArrayBase",
+ "QuickSortSpanBase", "QuickSortArrayBase"
+ );
+
+ static Action LookupFunc(object o)
+ {
+ TypeInfo t = typeof(SpanBench).GetTypeInfo();
+ MethodInfo m = t.GetDeclaredMethod((string) o);
+ return m.CreateDelegate(typeof(Action)) as Action;
+ }
+
+ public static int Main(string[] args)
+ {
+ bool result = true;
+
+ foreach(object[] o in TestFuncs)
+ {
+ string funcName = (string) o[0];
+ Action func = LookupFunc(funcName);
+ double timeInMs = Bench(func);
+ Console.WriteLine("{0}: {1}ms", funcName, timeInMs);
+ }
+
+ return (result ? 100 : -1);
+ }
+ }
+} \ No newline at end of file
diff --git a/tests/src/JIT/Performance/CodeQuality/Span/SpanBench.csproj b/tests/src/JIT/Performance/CodeQuality/Span/SpanBench.csproj
index e932acf2a2..ba240107ba 100644
--- a/tests/src/JIT/Performance/CodeQuality/Span/SpanBench.csproj
+++ b/tests/src/JIT/Performance/CodeQuality/Span/SpanBench.csproj
@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <!-- Always use latest Roslyn compiler -->
+ <Import Project="..\..\..\..\..\..\Tools\net45\roslyn\build\Microsoft.Net.Compilers.props"/>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>