Initial version extracted from Recyclable.Collections
This commit is contained in:
1 parent
86cda044c1
commit
7a2eaee0a6
8 files changed
+415
-2
No files matched your search
+10
@@ -0,0 +1,10 @@
|
||||
# License
|
||||
The project & source code is free for educational & personal use. **Any kind** of commercial use requires a donation, as prescribed below.
|
||||
|
||||
# Donation requirements for a life-time, commercial use
|
||||
* Commercial license is paid one time.
|
||||
* It can be obtained by donating $10 for each developer seat, using the link provided below. If you hire 2 developers, you need to donate $20 for a life-time, commercial use of this package.
|
||||
* Your license stays with you, if your developer moves somewhere else.
|
||||
|
||||
# Link for donations
|
||||
[](https://www.buymeacoffee.com/mlemanczyk)
|
||||
@@ -1,2 +1,8 @@
|
||||
# Recyclable.Collections.TestData
|
||||
TBD
|
||||
# Collections.Benchmarks.Core
|
||||
`Collections.Benchmarks.Core` project is a basic open source framework for performance measurements based on various collection types like `RecyclableList<T>`, `RecyclableLongList<T>`, `List<T>`, `SortableList<T>`, `PriorityQueue<T>` & similar.
|
||||
|
||||
## Included
|
||||
* `BaselineVsActualBenchmarkBase<T>`
|
||||
* `CollectionsBenchmarksBase<T>`
|
||||
* `DataGenerator`
|
||||
* `DoNothing`
|
||||
@@ -0,0 +1,25 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.7.34031.279
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Recyclable.Collections.TestData", "Recyclable.Collections.TestData\Recyclable.Collections.TestData.csproj", "{C78BEDC4-71C7-4893-B4A0-5C632E4D376E}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{C78BEDC4-71C7-4893-B4A0-5C632E4D376E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C78BEDC4-71C7-4893-B4A0-5C632E4D376E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C78BEDC4-71C7-4893-B4A0-5C632E4D376E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C78BEDC4-71C7-4893-B4A0-5C632E4D376E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {E83A8F25-1E42-4766-BAC6-E38822D64F8A}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,33 @@
|
||||
using System.Collections;
|
||||
|
||||
namespace Recyclable.Collections.TestData
|
||||
{
|
||||
public class CustomIList<T> : IList<T>
|
||||
{
|
||||
protected List<T> _list;
|
||||
|
||||
public CustomIList()
|
||||
{
|
||||
_list = new List<T>();
|
||||
}
|
||||
|
||||
public CustomIList(IEnumerable<T> items)
|
||||
{
|
||||
_list = new List<T>(items);
|
||||
}
|
||||
|
||||
public T this[int index] { get => _list[index]; set => _list[index] = value; }
|
||||
public int Count => _list.Count;
|
||||
public bool IsReadOnly => false;
|
||||
public void Add(T item) => _list.Add(item);
|
||||
public void Clear() => _list.Clear();
|
||||
public bool Contains(T item) => _list.Contains(item);
|
||||
public void CopyTo(T[] array, int arrayIndex) => _list.CopyTo(0, array, arrayIndex, _list.Count);
|
||||
public IEnumerator<T> GetEnumerator() => _list.GetEnumerator();
|
||||
public int IndexOf(T item) => _list.IndexOf(item);
|
||||
public void Insert(int index, T item) => _list.Insert(index, item);
|
||||
public bool Remove(T item) => _list.Remove(item);
|
||||
public void RemoveAt(int index) => _list.RemoveAt(index);
|
||||
IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System.Collections;
|
||||
|
||||
namespace Recyclable.Collections.TestData
|
||||
{
|
||||
public class EnumerableWithoutCount<T> : IEnumerable<T>
|
||||
{
|
||||
private readonly IEnumerable<T> _testData;
|
||||
|
||||
public EnumerableWithoutCount(IEnumerable<T> testData)
|
||||
{
|
||||
_testData = testData;
|
||||
}
|
||||
|
||||
public IEnumerator<T> GetEnumerator() => _testData.GetEnumerator();
|
||||
IEnumerator IEnumerable.GetEnumerator() => _testData.GetEnumerator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<OutputType>Library</OutputType>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<PackageId>Recyclable.Collections.TestData</PackageId>
|
||||
<PackageVersion>0.0.4</PackageVersion>
|
||||
<Authors>Marek Lemańczyk</Authors>
|
||||
<Company>N/A</Company>
|
||||
<Product>Recyclable.Collections.TestData</Product>
|
||||
<PackageTags>Recyclable Array Pool List Sortable Sort Benchmark Benchmarks Collection Collections Test Data</PackageTags>
|
||||
<Description>`Recyclable.Collections.TestData` project is a basic open source package for containing test data useful for testing collections like `RecyclableList<T>`, `RecyclableLongList<T>`, `List<T>`, `SortableList<T>`, `PriorityQueue<T>` & similar.</Description>
|
||||
<PackageProjectUrl>https://github.com/mlemanczyk/Recyclable.Collections.TestData</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/mlemanczyk/Recyclable.Collections.TestData</RepositoryUrl>
|
||||
<Copyright>Marek Lemańczyk 2023</Copyright>
|
||||
<PackageLicenseFile>LICENSE.md</PackageLicenseFile>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<PackageReleaseNotes>Initial version extracted from `Recyclable.Collections`</PackageReleaseNotes>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<PackageIcon>logo.png</PackageIcon>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="..\logo.png" Pack="true" PackagePath="" Link="logo.png" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="..\LICENSE.md" Pack="true" PackagePath="" Link="LICENSE.md" />
|
||||
<None Include="..\README.md" Pack="true" PackagePath="" Link="README.md" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="morelinq" Version="3.4.2" />
|
||||
<PackageReference Include="Open.Numeric.Primes" Version="3.0.0" />
|
||||
<PackageReference Include="Recyclable.Collections" Version="0.0.6" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,280 @@
|
||||
using MoreLinq;
|
||||
using Open.Numeric.Primes;
|
||||
using Recyclable.Collections;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Recyclable.Collections.TestData
|
||||
{
|
||||
public static class RecyclableLongListTestData
|
||||
{
|
||||
public static object[] SourceRefData { get; } = Enumerable.Range(1, 100).Cast<object>().ToArray();
|
||||
|
||||
public static IEnumerable<long> CreateTestData(long itemsCount)
|
||||
{
|
||||
for (long index = 1; index <= itemsCount; index++)
|
||||
{
|
||||
yield return index;
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<object> CreateRefTestData(long itemsCount)
|
||||
{
|
||||
for (long index = 1; index <= itemsCount; index++)
|
||||
{
|
||||
yield return index;
|
||||
}
|
||||
}
|
||||
|
||||
public static readonly IEnumerable<long> ItemsCountVariants = new long[]
|
||||
{
|
||||
//RecyclableDefaults.MinPooledArrayLength - 5, RecyclableDefaults.MinPooledArrayLength - 1, RecyclableDefaults.MinPooledArrayLength, RecyclableDefaults.MinPooledArrayLength + 1, RecyclableDefaults.MinPooledArrayLength + 5, 127, 128, 129, RecyclableDefaults.MinItemsCountForParallelization
|
||||
0, 1, 2, 3, 7, 10, 16, RecyclableDefaults.MinPooledArrayLength - 5, RecyclableDefaults.MinPooledArrayLength - 1, RecyclableDefaults.MinPooledArrayLength, RecyclableDefaults.MinPooledArrayLength + 1, RecyclableDefaults.MinPooledArrayLength + 5, RecyclableDefaults.MinPooledArrayLength * 100
|
||||
};
|
||||
|
||||
public static readonly IEnumerable<object[]> ItemsCountTestCases = ItemsCountVariants.Select(x => new object[] { (int)x });
|
||||
|
||||
public static readonly IEnumerable<int> BlockSizeVariants = new int[]
|
||||
{
|
||||
1, 2, 4, 16, RecyclableDefaults.MinPooledArrayLength - 5, (int)BitOperations.RoundUpToPowerOf2(RecyclableDefaults.MinPooledArrayLength)
|
||||
};
|
||||
|
||||
private static bool IsValidBlockSize(long itemsCount, long blockSize) => itemsCount is < 1024 || blockSize is > 8;
|
||||
|
||||
private static IEnumerable<object[]> GetTargetDataVariants()
|
||||
{
|
||||
foreach (var itemsCount in ItemsCountVariants)
|
||||
{
|
||||
foreach (var targetBlockSize in BlockSizeVariants)
|
||||
{
|
||||
if (!IsValidBlockSize(itemsCount, targetBlockSize))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
yield return new object[] { itemsCount, targetBlockSize };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> TargetDataVariants => GetTargetDataVariants();
|
||||
|
||||
private static IEnumerable<object[]> CombineSourceDataWithBlockSize(IEnumerable<object[]> sourceData)
|
||||
{
|
||||
foreach (var testData in sourceData)
|
||||
{
|
||||
foreach (var targetBlockSize in BlockSizeVariants)
|
||||
{
|
||||
if (!IsValidBlockSize((long)testData[2], targetBlockSize))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
yield return new object[] { testData[0], testData[1], testData[2], targetBlockSize };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<object[]> CreateSourceDataVariants(long itemsCount, bool refType)
|
||||
{
|
||||
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true);
|
||||
|
||||
switch (refType)
|
||||
{
|
||||
case false:
|
||||
long[] testData = CreateTestData(itemsCount).ToArray();
|
||||
|
||||
yield return new object[] { $"Array[{itemsCount}]", testData, itemsCount };
|
||||
yield return new object[] { $"ICollection[{itemsCount}]", testData, itemsCount };
|
||||
yield return new object[] { $"ICollection<T>[{itemsCount}]", testData, itemsCount };
|
||||
yield return new object[] { $"IEnumerable[{itemsCount}]", testData, itemsCount };
|
||||
yield return new object[] { $"IEnumerable<T>[{itemsCount}] without non-enumerated count", new EnumerableWithoutCount<long>(testData), itemsCount };
|
||||
yield return new object[] { $"IList<T>[{itemsCount}]", new CustomIList<long>(testData), itemsCount };
|
||||
yield return new object[] { $"IReadOnlyList<T>[{itemsCount}])", testData, itemsCount };
|
||||
yield return new object[] { $"List<T>[{itemsCount}]", testData.ToList(), itemsCount };
|
||||
yield return new object[] { $"ReadOnlySpan<T>[{itemsCount}]", testData, itemsCount };
|
||||
yield return new object[] { $"RecyclableList<T>[{itemsCount}]", testData.ToRecyclableList(), itemsCount };
|
||||
|
||||
foreach (var sourceBlockSize in BlockSizeVariants)
|
||||
{
|
||||
if (!IsValidBlockSize(itemsCount, sourceBlockSize))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
yield return new object[]
|
||||
{
|
||||
$"RecyclableLongList<T>[itemsCount: {itemsCount}, minBlockSize: {sourceBlockSize}]",
|
||||
testData.ToRecyclableLongList(sourceBlockSize),
|
||||
itemsCount
|
||||
};
|
||||
}
|
||||
|
||||
yield return new object[] { $"Span<T>[{itemsCount}]", testData, itemsCount };
|
||||
yield return new object[] { $"T[{itemsCount}]", testData, itemsCount };
|
||||
break;
|
||||
|
||||
case true:
|
||||
IEnumerable<object> testRefData = CreateRefTestData(itemsCount).ToArray();
|
||||
|
||||
yield return new object[] { $"Array[{itemsCount}]", testRefData, itemsCount };
|
||||
yield return new object[] { $"ICollection(itemsCount: {itemsCount}", testRefData, itemsCount };
|
||||
yield return new object[] { $"ICollection<T>(itemsCount: {itemsCount}", testRefData, itemsCount };
|
||||
yield return new object[] { $"IEnumerable(itemsCount: {itemsCount})", testRefData, itemsCount };
|
||||
yield return new object[] { $"IEnumerable<T>(itemsCount: {itemsCount}) without non-enumerated count", new EnumerableWithoutCount<object>(testRefData), itemsCount };
|
||||
yield return new object[] { $"IList<T>(itemsCount: {itemsCount})", new CustomIList<object>(testRefData), itemsCount };
|
||||
yield return new object[] { $"IReadOnlyList<T>(itemsCount: {itemsCount})", testRefData, itemsCount };
|
||||
yield return new object[] { $"List<T>(itemsCount: {itemsCount}", testRefData.ToList(), itemsCount };
|
||||
yield return new object[] { $"ReadOnlySpan<T>[{itemsCount}]", testRefData, itemsCount };
|
||||
yield return new object[] { $"RecyclableList<T>(itemsCount: {itemsCount})", testRefData.ToRecyclableList(), itemsCount };
|
||||
|
||||
foreach (var sourceBlockSize in BlockSizeVariants)
|
||||
{
|
||||
if (!IsValidBlockSize(itemsCount, sourceBlockSize))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
yield return new object[]
|
||||
{
|
||||
$"RecyclableLongList<T>(itemsCount: {itemsCount}, minBlockSize: {sourceBlockSize})",
|
||||
testRefData.ToRecyclableLongList(sourceBlockSize),
|
||||
itemsCount
|
||||
};
|
||||
}
|
||||
|
||||
yield return new object[] { $"Span<T>[{itemsCount}]", testRefData, itemsCount };
|
||||
yield return new object[] { $"T[{itemsCount}]", testRefData, itemsCount };
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<object[]> CreateSourceDataVariants(bool refType)
|
||||
{
|
||||
foreach (var itemsCount in ItemsCountVariants)
|
||||
{
|
||||
foreach (var variant in CreateSourceDataVariants(itemsCount, refType))
|
||||
{
|
||||
yield return variant;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> EmptySourceDataVariants => CreateSourceDataVariants(0, false);
|
||||
public static IEnumerable<object[]> SourceDataVariants => CreateSourceDataVariants(false);
|
||||
public static IEnumerable<object[]> SourceDataWithItemIndexVariants
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (var testCase in CreateSourceDataVariants(false).Where(testCase => (long)testCase[2] > 0))
|
||||
{
|
||||
var itemIndexes = CreateItemIndexVariants((long)testCase[2], RecyclableDefaults.BlockSize).ToArray();
|
||||
yield return new object[] { testCase[0], testCase[1], testCase[2], itemIndexes };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> SourceRefDataWithItemIndexVariants
|
||||
{
|
||||
get
|
||||
{
|
||||
IEnumerable<object[]> testCases = CreateSourceDataVariants(true).Where(testCase => (long)testCase[2] > 0);
|
||||
foreach (var testCase in testCases)
|
||||
{
|
||||
var itemIndexes = CreateItemIndexVariants((long)testCase[2], RecyclableDefaults.BlockSize).ToArray();
|
||||
|
||||
yield return new object[] { testCase[0], testCase[1], testCase[2], itemIndexes };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> SourceDataWithBlockSizeVariants => CombineSourceDataWithBlockSize(SourceDataVariants);
|
||||
public static IEnumerable<object[]> SourceRefDataVariants => CreateSourceDataVariants(true);
|
||||
public static IEnumerable<object[]> SourceRefDataWithBlockSizeVariants { get; } = CombineSourceDataWithBlockSize(SourceRefDataVariants);
|
||||
|
||||
private static IEnumerable<long> _initialItemIndexVariants => new long[] { 0, 1, 2, 3, 4, 5 };
|
||||
private static IEnumerable<long> CreateItemIndexVariants(long itemsCount, int blockSize)
|
||||
{
|
||||
IEnumerable<long> primes = _initialItemIndexVariants.Concat(
|
||||
_initialItemIndexVariants.SelectMany(index => new long[] { blockSize - index, blockSize + index })
|
||||
//new long[] { blockSize - 3, blockSize - 2, blockSize - 1, blockSize, blockSize + 1, blockSize + 2, blockSize + 3 }
|
||||
).ToArray();
|
||||
|
||||
IEnumerable<long> second = Prime.Numbers.StartingAt(7)
|
||||
.TakeUntil(prime =>
|
||||
prime > ((blockSize * 2) - 1) ||
|
||||
prime >= itemsCount
|
||||
);
|
||||
|
||||
primes = primes.Concat(second).ToArray();
|
||||
|
||||
primes = primes.Concat(
|
||||
primes.Select(index => itemsCount - index - 1)
|
||||
)
|
||||
.Where(index => itemsCount > 0 && index >= 0 && index < itemsCount).ToArray()
|
||||
.Distinct().ToArray();
|
||||
|
||||
return primes;
|
||||
|
||||
//IEnumerable<long> CreateItemIndexVariants()
|
||||
//{
|
||||
//if (itemsCount > 0)
|
||||
//{
|
||||
// yield return 0;
|
||||
//}
|
||||
|
||||
//foreach (long prime in primes)
|
||||
//{
|
||||
// yield return prime;
|
||||
|
||||
// long index = itemsCount - prime;
|
||||
// if (index >= 0)
|
||||
// {
|
||||
// yield return index;
|
||||
// }
|
||||
//}
|
||||
|
||||
//for (long index = itemsCount - (blockSize * 2) - 1; index < itemsCount; index++)
|
||||
//{
|
||||
// if (index >= 0)
|
||||
// {
|
||||
// yield return index;
|
||||
// }
|
||||
//}
|
||||
|
||||
//if ((blockSize / 16 * 16) + 1 < itemsCount)
|
||||
//{
|
||||
// yield return (blockSize / 16 * 16) + 1;
|
||||
//}
|
||||
//}
|
||||
|
||||
//return CreateItemIndexVariants();
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> CombineSourceRefDataWithBlockSizeWithItemIndex(bool refType)
|
||||
{
|
||||
IEnumerable<object[]> sourceData = refType switch
|
||||
{
|
||||
false => SourceDataWithBlockSizeVariants,
|
||||
true => SourceRefDataWithBlockSizeVariants
|
||||
};
|
||||
|
||||
foreach (var testCase in sourceData)
|
||||
{
|
||||
long itemsCount = (long)testCase[2];
|
||||
if (itemsCount == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
long[] itemIndexes = CreateItemIndexVariants(itemsCount, (int)testCase[3])
|
||||
.Where(_ => IsValidBlockSize((long)testCase[2], (int)testCase[3]))
|
||||
.ToArray();
|
||||
|
||||
yield return new object[] { testCase[0], testCase[1], (long)testCase[2], (int)testCase[3], itemIndexes };
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> SourceDataWithBlockSizeWithItemIndexVariants { get; } = CombineSourceRefDataWithBlockSizeWithItemIndex(false);
|
||||
public static IEnumerable<object[]> SourceRefDataWithBlockSizeWithItemIndexVariants { get; } = CombineSourceRefDataWithBlockSizeWithItemIndex(true);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user