-
Notifications
You must be signed in to change notification settings - Fork 272
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Span, ReadOnlySpan, Memory, ReadOnlyMemory constructors benchmarks * Span indexer benchmarks * move Clear Span and Array benchmarks to Clear benchmarks of all collections * move CopyTo Span and Array benchmarks to CopyTo benchmarks of all collections, add List and ImmutableArray CopyTo * make sure we always have the same random data to compare apples to apples * cleanup Sorting benchmarks * reorganize Span benchmarks * add For loop benchmark for ReadOnlySpan * we can't generate an array of more than 255 unique bytes so for some benchmarks we generate just random bytes * port MemoryMarshal benchmark from CoreFX * port more Span benchmarks * port more ROS Benchmarks * add benchmarks for creating Span from Memory * implement Slice benchmarks * implement foreach benchmarks for Span and ROS * add missing license header * add CopyTo benchmarks for ROS and Memory * and Memory.Pin benchmarks * simplify the slicing benchmark code * add memory.ToArray benchmarks * add GetPinnableReference benchmarks
- Loading branch information
1 parent
b978644
commit 4b34c30
Showing
38 changed files
with
1,286 additions
and
518 deletions.
There are no files selected for viewing
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
<PropertyGroup> | ||
<TargetFramework>netcoreapp2.1</TargetFramework> | ||
<IsPackable>false</IsPackable> | ||
</PropertyGroup> | ||
<ItemGroup> | ||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.0" /> | ||
<PackageReference Include="xunit" Version="2.3.1" /> | ||
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" /> | ||
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" /> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<ProjectReference Include="..\Benchmarks.csproj" /> | ||
</ItemGroup> | ||
</Project> |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
using System; | ||
using System.Linq; | ||
using Benchmarks; | ||
using Xunit; | ||
|
||
namespace Tests | ||
{ | ||
public class UniqueValuesGeneratorTests | ||
{ | ||
[Fact] | ||
public void UnsupportedTypesThrow() | ||
=> Assert.Throws<NotImplementedException>(() => ValuesGenerator.ArrayOfUniqueValues<UniqueValuesGeneratorTests>(1)); | ||
|
||
[Fact] | ||
public void GeneratedArraysContainOnlyUniqueValues() | ||
{ | ||
AssertGeneratedArraysContainOnlyUniqueValues<int>(1024); | ||
AssertGeneratedArraysContainOnlyUniqueValues<string>(1024); | ||
} | ||
|
||
private void AssertGeneratedArraysContainOnlyUniqueValues<T>(int size) | ||
{ | ||
var generatedArray = ValuesGenerator.ArrayOfUniqueValues<T>(size); | ||
|
||
var distinct = generatedArray.Distinct().ToArray(); | ||
|
||
Assert.Equal(distinct, generatedArray); | ||
} | ||
|
||
[Fact] | ||
public void GeneratedArraysContainAlwaysSameValues() | ||
{ | ||
AssertGeneratedArraysContainAlwaysSameValues<int>(1024); | ||
AssertGeneratedArraysContainAlwaysSameValues<string>(1024); | ||
} | ||
|
||
private void AssertGeneratedArraysContainAlwaysSameValues<T>(int size) | ||
{ | ||
var generatedArray = ValuesGenerator.ArrayOfUniqueValues<T>(size); | ||
|
||
for (int i = 0; i < 10; i++) | ||
{ | ||
var anotherGeneratedArray = ValuesGenerator.ArrayOfUniqueValues<T>(size); | ||
|
||
Assert.Equal(generatedArray, anotherGeneratedArray); | ||
} | ||
} | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
|
||
namespace Benchmarks | ||
{ | ||
public static class ValuesGenerator | ||
{ | ||
private const int Seed = 12345; // we always use the same seed to have repeatable results! | ||
|
||
public static T GetNonDefaultValue<T>() => ArrayOfUniqueValues<T>(2).First(value => !value.Equals(default)); | ||
|
||
public static T[] ArrayOfUniqueValues<T>(int count) | ||
{ | ||
var random = new Random(Seed); | ||
|
||
var uniqueValues = new HashSet<T>(); | ||
|
||
while (uniqueValues.Count != count) | ||
{ | ||
T value = GenerateValue<T>(random); | ||
|
||
if (!uniqueValues.Contains(value)) | ||
uniqueValues.Add(value); | ||
} | ||
|
||
return uniqueValues.ToArray(); | ||
} | ||
|
||
public static T[] Array<T>(int count) | ||
{ | ||
var random = new Random(Seed); | ||
|
||
var result = new T[count]; | ||
|
||
if (typeof(T) == typeof(byte)) | ||
{ | ||
random.NextBytes((byte[])(object)result); | ||
} | ||
else | ||
{ | ||
for (int i = 0; i < result.Length; i++) | ||
{ | ||
result[i] = GenerateValue<T>(random); | ||
} | ||
} | ||
|
||
return result; | ||
} | ||
|
||
public static Dictionary<TKey, TValue> Dictionary<TKey, TValue>(int count) | ||
{ | ||
var random = new Random(Seed); | ||
|
||
var dictionary = new Dictionary<TKey, TValue>(); | ||
|
||
while (dictionary.Count != count) | ||
{ | ||
TKey key = GenerateValue<TKey>(random); | ||
|
||
if (!dictionary.ContainsKey(key)) | ||
dictionary.Add(key, GenerateValue<TValue>(random)); | ||
} | ||
|
||
return dictionary; | ||
} | ||
|
||
private static T GenerateValue<T>(Random random) | ||
{ | ||
if (typeof(T) == typeof(char)) | ||
return (T)(object)(char)random.Next(char.MinValue, char.MaxValue); | ||
if (typeof(T) == typeof(int)) | ||
return (T)(object)random.Next(); | ||
if (typeof(T) == typeof(double)) | ||
return (T)(object)random.NextDouble(); | ||
if (typeof(T) == typeof(string)) | ||
return (T) (object) GenerateRandomString(random, 1, 50); | ||
|
||
throw new NotImplementedException($"{typeof(T).Name} is not implemented"); | ||
} | ||
|
||
private static string GenerateRandomString(Random random, int minLength, int maxLength) | ||
{ | ||
var length = random.Next(minLength, maxLength); | ||
|
||
var builder = new StringBuilder(length); | ||
for (int i = 0; i < length; i++) | ||
builder.Append((char) random.Next(char.MinValue, char.MaxValue)); | ||
|
||
return builder.ToString(); | ||
} | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
// 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; | ||
using System.Collections; | ||
using System.Runtime.CompilerServices; | ||
using BenchmarkDotNet.Attributes; | ||
using Benchmarks; | ||
|
||
namespace Span | ||
{ | ||
[BenchmarkCategory(Categories.CoreCLR)] | ||
[InvocationCount(InvocationsPerIteration)] | ||
public class Sorting | ||
{ | ||
private const int InvocationsPerIteration = 1000; | ||
|
||
[Params(Utils.DefaultCollectionSize)] | ||
public int Size; | ||
|
||
private int _iterationIndex = 0; | ||
private int[] _values; | ||
|
||
private int[][] _arrays; | ||
|
||
[GlobalSetup] | ||
public void Setup() => _values = ValuesGenerator.ArrayOfUniqueValues<int>(Size); | ||
|
||
[IterationSetup] | ||
public void SetupIteration() => Utils.FillArrays(ref _arrays, InvocationsPerIteration, _values); | ||
|
||
[IterationCleanup] | ||
public void CleanupIteration() => _iterationIndex = 0; // after every iteration end we set the index to 0 | ||
|
||
[BenchmarkCategory(Categories.Span)] | ||
[Benchmark] | ||
public void QuickSortSpan() => TestQuickSortSpan(new Span<int>(_arrays[_iterationIndex++])); | ||
|
||
[BenchmarkCategory(Categories.Span)] | ||
[Benchmark] | ||
public void BubbleSortSpan() => TestBubbleSortSpan(new Span<int>(_arrays[_iterationIndex++])); | ||
|
||
[Benchmark] | ||
public void QuickSortArray() => TestQuickSortArray(_arrays[_iterationIndex++], 0, Size); | ||
|
||
[Benchmark] | ||
public void BubbleSortArray() => TestBubbleSortArray(_arrays[_iterationIndex++]); | ||
|
||
[MethodImpl(MethodImplOptions.NoInlining)] | ||
static void TestQuickSortArray(int[] data, int lo, int hi) | ||
{ | ||
if (lo >= hi) | ||
{ | ||
return; | ||
} | ||
|
||
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 != hi) | ||
{ | ||
temp = data[i]; | ||
data[i] = pivot; | ||
data[hi] = temp; | ||
} | ||
|
||
TestQuickSortArray(data, lo, i - 1); | ||
TestQuickSortArray(data, i + 1, hi); | ||
} | ||
|
||
[MethodImpl(MethodImplOptions.NoInlining)] | ||
static void TestQuickSortSpan(Span<int> data) | ||
{ | ||
if (data.Length <= 1) | ||
{ | ||
return; | ||
} | ||
|
||
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 != hi) | ||
{ | ||
temp = data[i]; | ||
data[i] = pivot; | ||
data[hi] = temp; | ||
} | ||
|
||
TestQuickSortSpan(data.Slice(0, i)); | ||
TestQuickSortSpan(data.Slice(i + 1)); | ||
} | ||
|
||
[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; | ||
} | ||
while (swap); | ||
} | ||
|
||
[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; | ||
} | ||
while (swap); | ||
} | ||
} | ||
} |
Oops, something went wrong.