From 203b13268fa2718c7755097e5b9b533e1114819c Mon Sep 17 00:00:00 2001 From: mlemanczyk Date: Sat, 21 Oct 2023 17:29:53 +0200 Subject: [PATCH] List compatibility code moved to Recyclable.Collections.Compatibility.List package. Cleanup. --- LICENSE.md | 2 +- .../.gitattributes | 63 ++ Recyclable.Collections.Benchmarks/.gitignore | 6 + .../BinarySearch_BestAndWorstCases.cs | 65 -- .../Benchmarks/Contains_FirstItems.cs | 14 +- .../Benchmarks/Contains_LastItems.cs | 14 +- .../Benchmarks/ConvertAll.cs | 48 - .../Benchmarks/Count.cs | 14 +- .../Benchmarks/Create.cs | 11 +- .../Benchmarks/Create_WithCapacity.cs | 11 +- .../Benchmarks/Exists_BestAndWorstCases.cs | 65 -- .../Benchmarks/FindAll_BestAndWorstCases.cs | 80 -- .../FindLastIndex_BestAndWorstCases.cs | 63 -- .../Benchmarks/FindLast_BestAndWorstCases.cs | 53 - .../Benchmarks/Find_BestAndWorstCases.cs | 53 - .../Benchmarks/ForEach.cs | 28 +- .../Benchmarks/GetItem..cs | 28 +- .../Benchmarks/IndexOf_BestAndWorstCases.cs | 28 +- .../Benchmarks/IndexOf_FirstItems.cs | 16 +- .../Benchmarks/IndexOf_LastItems.cs | 16 +- .../Benchmarks/LongCount.cs | 8 +- .../RecyclableCollections.Benchmarks.cs | 153 +-- .../Benchmarks/Remove_FirstItems.cs | 9 +- .../Benchmarks/Remove_LastItems.cs | 9 +- .../Core/DataGenerator.cs | 19 - ...chmarks.cs => ArraySizeLimitBenchmarks.cs} | 13 +- .../POC/BoolOrCompareBenchmarks.cs | 66 ++ .../POC/BoolOrComparePoc.Benchmarks.cs | 63 -- .../POC/DelegateVsComparerBenchmarks.cs | 349 +++++++ .../POC/DelegateVsComparerPoc.Benchmarks.cs | 346 ------- ...lVsContainsInConsecutiveOrderBenchmarks.cs | 2 +- ...terOperatorVsNotEqualOperatorBenchmarks.cs | 50 + ...peratorvsDoesntEqualOperator.Benchmarks.cs | 57 -- .../LessOperatorvsAndOperatorBenchmarks.cs | 18 +- .../POC/ModuloBenchmarks.cs | 371 +++++++ .../POC/ModuloPoc.Benchmarks.cs | 376 ------- .../POC/PocBenchmarkBase.cs | 142 --- ... RecyclableLongListBenchmarks.IndexOf.txt} | 0 .../RecyclableLongListBenchmarks.cs} | 128 +-- .../POC/RecyclableLongListPoc.Benchmarks.cs | 47 - .../POC/RefVsInstanceMemberBenchmarks.cs | 360 +++++++ .../POC/RefVsInstanceMemberPoc.Benchmarks.cs | 364 ------- .../POC/RoundBenchmarks.cs | 9 +- ...rs.cs => RoundUpToPowerOf2Alternatives.cs} | 29 +- ...SpanConstructorVsTypecasting.Benchmarks.cs | 64 -- .../SpanConstructorVsTypecastingBenchmarks.cs | 63 ++ .../POC/SpanVsArrayBenchmarks.cs | 9 +- Recyclable.Collections.Benchmarks/Program.cs | 31 +- .../Recyclable.Collections.Benchmarks.csproj | 2 +- .../Recyclable.Collections.csproj | 10 +- .../RecyclableList.Compatibility.List.Find.cs | 272 ----- ...cyclableList.Compatibility.List.IndexOf.cs | 26 - ...ableList.Compatibility.List.InsertRange.cs | 358 ------- .../RecyclableList.Compatibility.List.cs | 214 ---- Recyclable.CollectionsTests/CustomIList.cs | 33 - .../EnumerableWithoutCount.cs | 17 - .../Recyclable.CollectionsTests.csproj | 13 +- .../RecyclableListTests.cs | 948 +----------------- .../RecyclableLongListTestData.cs | 282 ------ .../RecyclableLongListTests.cs | 1 + logo.png | Bin 0 -> 14559 bytes 61 files changed, 1634 insertions(+), 4375 deletions(-) create mode 100644 Recyclable.Collections.Benchmarks/.gitattributes create mode 100644 Recyclable.Collections.Benchmarks/.gitignore delete mode 100644 Recyclable.Collections.Benchmarks/Benchmarks/BinarySearch_BestAndWorstCases.cs delete mode 100644 Recyclable.Collections.Benchmarks/Benchmarks/ConvertAll.cs delete mode 100644 Recyclable.Collections.Benchmarks/Benchmarks/Exists_BestAndWorstCases.cs delete mode 100644 Recyclable.Collections.Benchmarks/Benchmarks/FindAll_BestAndWorstCases.cs delete mode 100644 Recyclable.Collections.Benchmarks/Benchmarks/FindLastIndex_BestAndWorstCases.cs delete mode 100644 Recyclable.Collections.Benchmarks/Benchmarks/FindLast_BestAndWorstCases.cs delete mode 100644 Recyclable.Collections.Benchmarks/Benchmarks/Find_BestAndWorstCases.cs delete mode 100644 Recyclable.Collections.Benchmarks/Core/DataGenerator.cs rename Recyclable.Collections.Benchmarks/POC/{ArraySizeLimitPoc.Benchmarks.cs => ArraySizeLimitBenchmarks.cs} (82%) create mode 100644 Recyclable.Collections.Benchmarks/POC/BoolOrCompareBenchmarks.cs delete mode 100644 Recyclable.Collections.Benchmarks/POC/BoolOrComparePoc.Benchmarks.cs create mode 100644 Recyclable.Collections.Benchmarks/POC/DelegateVsComparerBenchmarks.cs delete mode 100644 Recyclable.Collections.Benchmarks/POC/DelegateVsComparerPoc.Benchmarks.cs create mode 100644 Recyclable.Collections.Benchmarks/POC/GreaterOperatorVsNotEqualOperatorBenchmarks.cs delete mode 100644 Recyclable.Collections.Benchmarks/POC/GreaterOperatorvsDoesntEqualOperator.Benchmarks.cs create mode 100644 Recyclable.Collections.Benchmarks/POC/ModuloBenchmarks.cs delete mode 100644 Recyclable.Collections.Benchmarks/POC/ModuloPoc.Benchmarks.cs delete mode 100644 Recyclable.Collections.Benchmarks/POC/PocBenchmarkBase.cs rename Recyclable.Collections.Benchmarks/POC/{RecyclableLongListPos.Benchmarks.IndexOf.txt => RecyclableLongListBenchmarks.IndexOf.txt} (100%) rename Recyclable.Collections.Benchmarks/{RecyclableBenchmarkBase.cs => POC/RecyclableLongListBenchmarks.cs} (53%) delete mode 100644 Recyclable.Collections.Benchmarks/POC/RecyclableLongListPoc.Benchmarks.cs create mode 100644 Recyclable.Collections.Benchmarks/POC/RefVsInstanceMemberBenchmarks.cs delete mode 100644 Recyclable.Collections.Benchmarks/POC/RefVsInstanceMemberPoc.Benchmarks.cs rename Recyclable.Collections.Benchmarks/POC/{RoundUpToPowerOf2vsOthers.cs => RoundUpToPowerOf2Alternatives.cs} (75%) delete mode 100644 Recyclable.Collections.Benchmarks/POC/SpanConstructorVsTypecasting.Benchmarks.cs create mode 100644 Recyclable.Collections.Benchmarks/POC/SpanConstructorVsTypecastingBenchmarks.cs delete mode 100644 Recyclable.Collections/RecyclableList.Compatibility.List.Find.cs delete mode 100644 Recyclable.Collections/RecyclableList.Compatibility.List.IndexOf.cs delete mode 100644 Recyclable.Collections/RecyclableList.Compatibility.List.InsertRange.cs delete mode 100644 Recyclable.Collections/RecyclableList.Compatibility.List.cs delete mode 100644 Recyclable.CollectionsTests/CustomIList.cs delete mode 100644 Recyclable.CollectionsTests/EnumerableWithoutCount.cs delete mode 100644 Recyclable.CollectionsTests/RecyclableLongListTestData.cs create mode 100644 logo.png diff --git a/LICENSE.md b/LICENSE.md index b345ef8..0da7cad 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -3,7 +3,7 @@ The project & source code is free for educational & personal use. **Any # Donation requirements for a life-time, commercial use * Commercial license is paid one time. -* It can be obtained by donaiting $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. +* 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 diff --git a/Recyclable.Collections.Benchmarks/.gitattributes b/Recyclable.Collections.Benchmarks/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/Recyclable.Collections.Benchmarks/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/Recyclable.Collections.Benchmarks/.gitignore b/Recyclable.Collections.Benchmarks/.gitignore new file mode 100644 index 0000000..da47c84 --- /dev/null +++ b/Recyclable.Collections.Benchmarks/.gitignore @@ -0,0 +1,6 @@ +################################################################################ +# This .gitignore file was automatically created by Microsoft(R) Visual Studio. +################################################################################ + +/bin +/obj diff --git a/Recyclable.Collections.Benchmarks/Benchmarks/BinarySearch_BestAndWorstCases.cs b/Recyclable.Collections.Benchmarks/Benchmarks/BinarySearch_BestAndWorstCases.cs deleted file mode 100644 index 3f5abd3..0000000 --- a/Recyclable.Collections.Benchmarks/Benchmarks/BinarySearch_BestAndWorstCases.cs +++ /dev/null @@ -1,65 +0,0 @@ -namespace Recyclable.Collections.Benchmarks -{ - public partial class RecyclableCollectionsBenchmarks - { - public void Array_BinarySearch_BestAndWorstCases() - { - var data = TestObjects; - var list = TestObjects; - var dataCount = TestObjectCountForSlowMethods; - for (var i = 0; i < dataCount; i++) - { - DoNothing(Array.BinarySearch(list, data[i])); - DoNothing(Array.BinarySearch(list, data[^(i + 1)])); - } - } - - public void List_BinarySearch_BestAndWorstCases() - { - var data = TestObjects; - var list = TestObjectsAsList; - var dataCount = TestObjectCountForSlowMethods; - for (var i = 0; i < dataCount; i++) - { - DoNothing(list.BinarySearch(data[i])); - DoNothing(list.BinarySearch(data[^(i + 1)])); - } - } - - public void PooledList_BinarySearch_BestAndWorstCases() - { - var data = TestObjects; - var list = TestObjectsAsPooledList; - var dataCount = TestObjectCountForSlowMethods; - for (var i = 0; i < dataCount; i++) - { - DoNothing(list.BinarySearch(data[i])); - DoNothing(list.BinarySearch(data[^(i + 1)])); - } - } - - public void RecyclableList_BinarySearch_BestAndWorstCases() - { - var data = TestObjects; - var list = TestObjectsAsRecyclableList; - var dataCount = TestObjectCountForSlowMethods; - for (var i = 0; i < dataCount; i++) - { - DoNothing(list.BinarySearch(data[i])); - DoNothing(list.BinarySearch(data[^(i + 1)])); - } - } - - // public void RecyclableLongList_BinarySearch_BestAndWorstCases() - // { - // var data = TestObjects; - // var list = TestObjectsAsRecyclableLongList; - // var dataCount = TestObjectCountForSlowMethods; - // for (var i = 0; i < dataCount; i++) - // { - // DoNothing(list.BinarySearch(data[i])); - // DoNothing(list.BinarySearch(data[^(i + 1)])); - // } - // } - } -} diff --git a/Recyclable.Collections.Benchmarks/Benchmarks/Contains_FirstItems.cs b/Recyclable.Collections.Benchmarks/Benchmarks/Contains_FirstItems.cs index 07c1901..7ea92b7 100644 --- a/Recyclable.Collections.Benchmarks/Benchmarks/Contains_FirstItems.cs +++ b/Recyclable.Collections.Benchmarks/Benchmarks/Contains_FirstItems.cs @@ -1,4 +1,6 @@ -namespace Recyclable.Collections.Benchmarks +using Collections.Benchmarks.Core; + +namespace Recyclable.Collections.Benchmarks { public partial class RecyclableCollectionsBenchmarks { @@ -9,7 +11,7 @@ var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount; for (var i = 0; i < dataCount; i++) { - DoNothing(Array.IndexOf(list, data[i]) >= 0); + DoNothing.With(Array.IndexOf(list, data[i]) >= 0); } } @@ -20,7 +22,7 @@ var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount; for (var i = 0; i < dataCount; i++) { - DoNothing(list.Contains(data[i])); + DoNothing.With(list.Contains(data[i])); } } @@ -31,7 +33,7 @@ var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount; for (var i = 0; i < dataCount; i++) { - DoNothing(list.Contains(data[i])); + DoNothing.With(list.Contains(data[i])); } } @@ -42,7 +44,7 @@ var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount; for (var i = 0; i < dataCount; i++) { - DoNothing(list.Contains(data[i])); + DoNothing.With(list.Contains(data[i])); } } @@ -53,7 +55,7 @@ var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount; for (var i = 0; i < dataCount; i++) { - DoNothing(list.Contains(data[i])); + DoNothing.With(list.Contains(data[i])); } } } diff --git a/Recyclable.Collections.Benchmarks/Benchmarks/Contains_LastItems.cs b/Recyclable.Collections.Benchmarks/Benchmarks/Contains_LastItems.cs index 30a5dfe..aac5aa9 100644 --- a/Recyclable.Collections.Benchmarks/Benchmarks/Contains_LastItems.cs +++ b/Recyclable.Collections.Benchmarks/Benchmarks/Contains_LastItems.cs @@ -1,4 +1,6 @@ -namespace Recyclable.Collections.Benchmarks +using Collections.Benchmarks.Core; + +namespace Recyclable.Collections.Benchmarks { public partial class RecyclableCollectionsBenchmarks { @@ -9,7 +11,7 @@ var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount; for (var i = 0; i < dataCount; i++) { - DoNothing(list.Contains(data[^(i + 1)])); + DoNothing.With(list.Contains(data[^(i + 1)])); } } @@ -20,7 +22,7 @@ var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount; for (var i = 0; i < dataCount; i++) { - DoNothing(list.Contains(data[^(i + 1)])); + DoNothing.With(list.Contains(data[^(i + 1)])); } } @@ -31,7 +33,7 @@ var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount; for (var i = 0; i < dataCount; i++) { - DoNothing(list.Contains(data[^(i + 1)])); + DoNothing.With(list.Contains(data[^(i + 1)])); } } @@ -42,7 +44,7 @@ var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount; for (var i = 0; i < dataCount; i++) { - DoNothing(list.Contains(data[^(i + 1)])); + DoNothing.With(list.Contains(data[^(i + 1)])); } } @@ -53,7 +55,7 @@ var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount; for (var i = 0; i < dataCount; i++) { - DoNothing(list.Contains(data[^(i + 1)])); + DoNothing.With(list.Contains(data[^(i + 1)])); } } } diff --git a/Recyclable.Collections.Benchmarks/Benchmarks/ConvertAll.cs b/Recyclable.Collections.Benchmarks/Benchmarks/ConvertAll.cs deleted file mode 100644 index 55ec249..0000000 --- a/Recyclable.Collections.Benchmarks/Benchmarks/ConvertAll.cs +++ /dev/null @@ -1,48 +0,0 @@ -namespace Recyclable.Collections.Benchmarks -{ - public partial class RecyclableCollectionsBenchmarks - { - public void Array_ConvertAll() - { - var data = TestObjects; - var list = TestObjects; - var dataCount = TestObjectCountForSlowMethods; - DoNothing(Array.ConvertAll(list, static (item) => (long) item)); - } - - public void List_ConvertAll() - { - var data = TestObjects; - var list = TestObjectsAsList; - var dataCount = TestObjectCountForSlowMethods; - DoNothing(list.ConvertAll(static (item) => (long)item)); - } - - public void PooledList_ConvertAll() - { - var data = TestObjects; - var list = TestObjectsAsPooledList; - var dataCount = TestObjectCountForSlowMethods; - using var converted = list.ConvertAll(static (item) => (long)item); - DoNothing(converted); - } - - public void RecyclableList_ConvertAll() - { - var data = TestObjects; - var list = TestObjectsAsRecyclableList; - var dataCount = TestObjectCountForSlowMethods; - using RecyclableList converted = list.ConvertAll(static (item) => (long)item); - DoNothing(converted); - } - - // public void RecyclableLongList_ConvertAll() - // { - // var data = TestObjects; - // var list = TestObjectsAsRecyclableLongList; - // var dataCount = TestObjectCountForSlowMethods; - // using RecyclableList converted = list.ConvertAll(static (item) => (long)item); - // DoNothing(converted); - // } - } -} diff --git a/Recyclable.Collections.Benchmarks/Benchmarks/Count.cs b/Recyclable.Collections.Benchmarks/Benchmarks/Count.cs index 7c30a64..3567a66 100644 --- a/Recyclable.Collections.Benchmarks/Benchmarks/Count.cs +++ b/Recyclable.Collections.Benchmarks/Benchmarks/Count.cs @@ -1,35 +1,37 @@ -namespace Recyclable.Collections.Benchmarks +using Collections.Benchmarks.Core; + +namespace Recyclable.Collections.Benchmarks { public partial class RecyclableCollectionsBenchmarks { public void Array_Count() { var data = TestObjects; - DoNothing(data.Length); + DoNothing.With(data.Length); } public void List_Count() { var data = TestObjectsAsList; - DoNothing(data.Count); + DoNothing.With(data.Count); } public void PooledList_Count() { var data = TestObjectsAsPooledList; - DoNothing(data.Count); + DoNothing.With(data.Count); } public void RecyclableList_Count() { var data = TestObjectsAsRecyclableList; - DoNothing(data.Count); + DoNothing.With(data.Count); } public void RecyclableLongList_Count() { var data = TestObjectsAsRecyclableLongList; - DoNothing(data.Count); + DoNothing.With(data.Count); } } } diff --git a/Recyclable.Collections.Benchmarks/Benchmarks/Create.cs b/Recyclable.Collections.Benchmarks/Benchmarks/Create.cs index d10adf0..f4c69bc 100644 --- a/Recyclable.Collections.Benchmarks/Benchmarks/Create.cs +++ b/Recyclable.Collections.Benchmarks/Benchmarks/Create.cs @@ -1,4 +1,5 @@ using Collections.Pooled; +using Collections.Benchmarks.Core; #pragma warning disable CA1822, CA1825 @@ -9,31 +10,31 @@ namespace Recyclable.Collections.Benchmarks public void Array_Create() { var list = new int[0]; - DoNothing(list); + DoNothing.With(list); } public void List_Create() { var list = new List(); - DoNothing(list); + DoNothing.With(list); } public void PooledList_Create() { using var list = new PooledList(ClearMode.Auto); - DoNothing(list); + DoNothing.With(list); } public void RecyclableList_Create() { using var list = new RecyclableList(); - DoNothing(list); + DoNothing.With(list); } public void RecyclableLongList_Create() { using var list = new RecyclableLongList(); - DoNothing(list); + DoNothing.With(list); } } } diff --git a/Recyclable.Collections.Benchmarks/Benchmarks/Create_WithCapacity.cs b/Recyclable.Collections.Benchmarks/Benchmarks/Create_WithCapacity.cs index cb5b584..8994574 100644 --- a/Recyclable.Collections.Benchmarks/Benchmarks/Create_WithCapacity.cs +++ b/Recyclable.Collections.Benchmarks/Benchmarks/Create_WithCapacity.cs @@ -1,4 +1,5 @@ using Collections.Pooled; +using Collections.Benchmarks.Core; namespace Recyclable.Collections.Benchmarks { @@ -7,31 +8,31 @@ namespace Recyclable.Collections.Benchmarks public void Array_Create_WithCapacity() { var data = new int[TestObjectCount]; - DoNothing(data); + DoNothing.With(data); } public void List_Create_WithCapacity() { var list = new List(TestObjectCount); - DoNothing(list); + DoNothing.With(list); } public void PooledList_Create_WithCapacity() { using var list = new PooledList(capacity: TestObjectCount, ClearMode.Auto); - DoNothing(list); + DoNothing.With(list); } public void RecyclableList_Create_WithCapacity() { using var list = new RecyclableList(TestObjectCount); - DoNothing(list); + DoNothing.With(list); } public void RecyclableLongList_Create_WithCapacity() { using var list = new RecyclableLongList(minBlockSize: BlockSize, initialCapacity: TestObjectCount); - DoNothing(list); + DoNothing.With(list); } } } diff --git a/Recyclable.Collections.Benchmarks/Benchmarks/Exists_BestAndWorstCases.cs b/Recyclable.Collections.Benchmarks/Benchmarks/Exists_BestAndWorstCases.cs deleted file mode 100644 index f2d7b3f..0000000 --- a/Recyclable.Collections.Benchmarks/Benchmarks/Exists_BestAndWorstCases.cs +++ /dev/null @@ -1,65 +0,0 @@ -namespace Recyclable.Collections.Benchmarks -{ - public partial class RecyclableCollectionsBenchmarks - { - public void Array_Exists_BestAndWorstCases() - { - var data = TestObjects; - var list = TestObjects; - var dataCount = TestObjectCountForSlowMethods; - for (var i = 0; i < dataCount; i++) - { - DoNothing(Array.Exists(list, (x) => x == data[i])); - DoNothing(Array.Exists(list, (x) => x == data[^(i + 1)])); - } - } - - public void List_Exists_BestAndWorstCases() - { - var data = TestObjects; - var list = TestObjectsAsList; - var dataCount = TestObjectCountForSlowMethods; - for (var i = 0; i < dataCount; i++) - { - DoNothing(list.Exists((x) => x == data[i])); - DoNothing(list.Exists((x) => x == data[^(i + 1)])); - } - } - - public void PooledList_Exists_BestAndWorstCases() - { - var data = TestObjects; - var list = TestObjectsAsPooledList; - var dataCount = TestObjectCountForSlowMethods; - for (var i = 0; i < dataCount; i++) - { - DoNothing(list.Exists((x) => x == data[i])); - DoNothing(list.Exists((x) => x == data[^(i + 1)])); - } - } - - public void RecyclableList_Exists_BestAndWorstCases() - { - var data = TestObjects; - var list = TestObjectsAsRecyclableList; - var dataCount = TestObjectCountForSlowMethods; - for (var i = 0; i < dataCount; i++) - { - DoNothing(list.Exists((x) => x == data[i])); - DoNothing(list.Exists((x) => x == data[^(i + 1)])); - } - } - - // public void RecyclableLongList_Exists_BestAndWorstCases() - // { - // var data = TestObjects; - // var list = TestObjectsAsRecyclableLongList; - // var dataCount = TestObjectCountForSlowMethods; - // for (var i = 0; i < dataCount; i++) - // { - // DoNothing(list.Exists((x) => x == data[i])); - // DoNothing(list.Exists((x) => x == data[^(i + 1)])); - // } - // } - } -} diff --git a/Recyclable.Collections.Benchmarks/Benchmarks/FindAll_BestAndWorstCases.cs b/Recyclable.Collections.Benchmarks/Benchmarks/FindAll_BestAndWorstCases.cs deleted file mode 100644 index fb4443c..0000000 --- a/Recyclable.Collections.Benchmarks/Benchmarks/FindAll_BestAndWorstCases.cs +++ /dev/null @@ -1,80 +0,0 @@ -namespace Recyclable.Collections.Benchmarks -{ - public partial class RecyclableCollectionsBenchmarks - { - public void Array_FindAll_BestAndWorstCases() - { - var data = TestObjects; - var list = TestObjects; - var dataCount = TestObjectCountForSlowMethods; - for (var i = 0; i < dataCount; i++) - { - DoNothing(Array.FindAll(list, (item) => item == data[i])); - DoNothing(Array.FindAll(list, (item) => item == data[^(i + 1)])); - } - } - - public void List_FindAll_BestAndWorstCases() - { - var data = TestObjects; - var list = TestObjectsAsList; - var dataCount = TestObjectCountForSlowMethods; - for (var i = 0; i < dataCount; i++) - { - DoNothing(list.FindAll((item) => item == data[i])); - DoNothing(list.FindAll((item) => item == data[^(i + 1)])); - } - } - - public void PooledList_FindAll_BestAndWorstCases() - { - var data = TestObjects; - var list = TestObjectsAsPooledList; - var dataCount = TestObjectCountForSlowMethods; - for (var i = 0; i < dataCount; i++) - { - var temp = list.FindAll((item) => item == data[i]); - DoNothing(temp); - temp.Dispose(); - - temp = list.FindAll((item) => item == data[^(i + 1)]); - DoNothing(temp); - temp.Dispose(); - } - } - - public void RecyclableList_FindAll_BestAndWorstCases() - { - var data = TestObjects; - var list = TestObjectsAsRecyclableList; - var dataCount = TestObjectCountForSlowMethods; - for (var i = 0; i < dataCount; i++) - { - var temp = list.FindAll((item) => item == data[i]); - DoNothing(temp); - temp.Dispose(); - - temp = list.FindAll((item) => item == data[^(i + 1)]); - DoNothing(temp); - temp.Dispose(); - } - } - - // public void RecyclableLongList_FindAll_BestAndWorstCases() - // { - // var data = TestObjects; - // var list = TestObjectsAsRecyclableLongList; - // var dataCount = TestObjectCountForSlowMethods; - // for (var i = 0; i < dataCount; i++) - // { - // var temp = list.FindAll((item) => item == data[i]); - // DoNothing(temp); - // temp.Dispose(); - - // temp = list.FindAll((item) => item == data[^(i + 1)]); - // DoNothing(temp); - // temp.Dispose(); - // } - // } - } -} diff --git a/Recyclable.Collections.Benchmarks/Benchmarks/FindLastIndex_BestAndWorstCases.cs b/Recyclable.Collections.Benchmarks/Benchmarks/FindLastIndex_BestAndWorstCases.cs deleted file mode 100644 index b7338e1..0000000 --- a/Recyclable.Collections.Benchmarks/Benchmarks/FindLastIndex_BestAndWorstCases.cs +++ /dev/null @@ -1,63 +0,0 @@ -namespace Recyclable.Collections.Benchmarks -{ - public partial class RecyclableCollectionsBenchmarks - { - public void Array_FindLastIndex_BestAndWorstCases() - { - var data = TestObjects; - var list = TestObjects; - var dataCount = TestObjectCountForSlowMethods; - // Console.WriteLine($"{nameof(TestObjectCount)}={TestObjectCount}"); - // Console.WriteLine($"{nameof(TestObjectCountForSlowMethods)}={TestObjectCountForSlowMethods}"); - for (var i = 0; i < dataCount; i++) - { - // Console.WriteLine($"data.Length={data.Length}"); - // Console.WriteLine($"{nameof(TestObjectCount)}={TestObjectCount}"); - // Console.WriteLine($"{nameof(TestObjectCountForSlowMethods)}={TestObjectCountForSlowMethods}"); - DoNothing(Array.FindLastIndex(list, 0, (x) => x == data[i])); - DoNothing(Array.FindLastIndex(list, 0, (x) => x == data[^(i + 1)])); - } - } - - public void List_FindLastIndex_BestAndWorstCases() - { - var data = TestObjects; - var list = TestObjectsAsList; - var dataCount = TestObjectCountForSlowMethods; - // Console.WriteLine($"{nameof(TestObjectCount)}={TestObjectCount}"); - // Console.WriteLine($"{nameof(TestObjectCountForSlowMethods)}={TestObjectCountForSlowMethods}"); - for (var i = 0; i < dataCount; i++) - { - // Console.WriteLine($"data.Length={data.Length}"); - // Console.WriteLine($"{nameof(TestObjectCount)}={TestObjectCount}"); - // Console.WriteLine($"{nameof(TestObjectCountForSlowMethods)}={TestObjectCountForSlowMethods}"); - DoNothing(list.FindLastIndex(0, (x) => x == data[i])); - DoNothing(list.FindLastIndex(0, (x) => x == data[^(i + 1)])); - } - } - - public void RecyclableList_FindLastIndex_BestAndWorstCases() - { - var data = TestObjects; - var list = TestObjectsAsRecyclableList; - var dataCount = TestObjectCountForSlowMethods; - for (var i = 0; i < dataCount; i++) - { - DoNothing(list.FindLastIndex(0, (x) => x == data[i])); - DoNothing(list.FindLastIndex(0, (x) => x == data[^(i + 1)])); - } - } - - // public void RecyclableLongList_FindLastIndex_BestAndWorstCases() - // { - // var data = TestObjects; - // var list = TestObjectsAsRecyclableLongList; - // var dataCount = TestObjectCountForSlowMethods; - // for (var i = 0; i < dataCount; i++) - // { - // DoNothing(list.FindLastIndex(0, (x) => x == data[i])); - // DoNothing(list.FindLastIndex(0, (x) => x == data[^(i + 1)])); - // } - // } - } -} diff --git a/Recyclable.Collections.Benchmarks/Benchmarks/FindLast_BestAndWorstCases.cs b/Recyclable.Collections.Benchmarks/Benchmarks/FindLast_BestAndWorstCases.cs deleted file mode 100644 index ef7ac79..0000000 --- a/Recyclable.Collections.Benchmarks/Benchmarks/FindLast_BestAndWorstCases.cs +++ /dev/null @@ -1,53 +0,0 @@ -namespace Recyclable.Collections.Benchmarks -{ - public partial class RecyclableCollectionsBenchmarks - { - public void Array_FindLast_BestAndWorstCases() - { - var data = TestObjects; - var list = TestObjects; - var dataCount = TestObjectCountForSlowMethods; - for (var i = 0; i < dataCount; i++) - { - DoNothing(Array.FindLast(list, (x) => x == data[i])); - DoNothing(Array.FindLast(list, (x) => x == data[^(i + 1)])); - } - } - - public void List_FindLast_BestAndWorstCases() - { - var data = TestObjects; - var list = TestObjectsAsList; - var dataCount = TestObjectCountForSlowMethods; - for (var i = 0; i < dataCount; i++) - { - DoNothing(list.FindLast((x) => x == data[i])); - DoNothing(list.FindLast((x) => x == data[^(i + 1)])); - } - } - - public void RecyclableList_FindLast_BestAndWorstCases() - { - var data = TestObjects; - var list = TestObjectsAsRecyclableList; - var dataCount = TestObjectCountForSlowMethods; - for (var i = 0; i < dataCount; i++) - { - DoNothing(list.FindLast((x) => x == data[i])); - DoNothing(list.FindLast((x) => x == data[^(i + 1)])); - } - } - - // public void RecyclableLongList_FindLast_BestAndWorstCases() - // { - // var data = TestObjects; - // var list = TestObjectsAsRecyclableLongList; - // var dataCount = TestObjectCountForSlowMethods; - // for (var i = 0; i < dataCount; i++) - // { - // DoNothing(list.FindLast((x) => x == data[i])); - // DoNothing(list.FindLast((x) => x == data[^(i + 1)])); - // } - // } - } -} diff --git a/Recyclable.Collections.Benchmarks/Benchmarks/Find_BestAndWorstCases.cs b/Recyclable.Collections.Benchmarks/Benchmarks/Find_BestAndWorstCases.cs deleted file mode 100644 index 4f677da..0000000 --- a/Recyclable.Collections.Benchmarks/Benchmarks/Find_BestAndWorstCases.cs +++ /dev/null @@ -1,53 +0,0 @@ -namespace Recyclable.Collections.Benchmarks -{ - public partial class RecyclableCollectionsBenchmarks - { - public void Array_Find_BestAndWorstCases() - { - var data = TestObjects; - var list = TestObjects; - var dataCount = TestObjectCountForSlowMethods; - for (var i = 0; i < dataCount; i++) - { - DoNothing(Array.Find(list, (x) => x == data[i])); - DoNothing(Array.Find(list, (x) => x == data[^(i + 1)])); - } - } - - public void List_Find_BestAndWorstCases() - { - var data = TestObjects; - var list = TestObjectsAsList; - var dataCount = TestObjectCountForSlowMethods; - for (var i = 0; i < dataCount; i++) - { - DoNothing(list.Find((x) => x == data[i])); - DoNothing(list.Find((x) => x == data[^(i + 1)])); - } - } - - public void RecyclableList_Find_BestAndWorstCases() - { - var data = TestObjects; - var list = TestObjectsAsRecyclableList; - var dataCount = TestObjectCountForSlowMethods; - for (var i = 0; i < dataCount; i++) - { - DoNothing(list.Find((x) => x == data[i])); - DoNothing(list.Find((x) => x == data[^(i + 1)])); - } - } - - // public void RecyclableLongList_Find_BestAndWorstCases() - // { - // var data = TestObjects; - // var list = TestObjectsAsRecyclableLongList; - // var dataCount = TestObjectCountForSlowMethods; - // for (var i = 0; i < dataCount; i++) - // { - // DoNothing(list.Find((x) => x == data[i])); - // DoNothing(list.Find((x) => x == data[^(i + 1)])); - // } - // } - } -} diff --git a/Recyclable.Collections.Benchmarks/Benchmarks/ForEach.cs b/Recyclable.Collections.Benchmarks/Benchmarks/ForEach.cs index b3df02a..2599620 100644 --- a/Recyclable.Collections.Benchmarks/Benchmarks/ForEach.cs +++ b/Recyclable.Collections.Benchmarks/Benchmarks/ForEach.cs @@ -1,4 +1,6 @@ -namespace Recyclable.Collections.Benchmarks +using Collections.Benchmarks.Core; + +namespace Recyclable.Collections.Benchmarks { public partial class RecyclableCollectionsBenchmarks { @@ -6,7 +8,7 @@ { foreach (var item in TestObjects) { - DoNothing(item); + DoNothing.With(item); } } @@ -14,7 +16,7 @@ { foreach (var item in TestObjects) { - DoNothing(item); + DoNothing.With(item); } } @@ -22,7 +24,7 @@ { foreach (var item in TestObjectsAsList) { - DoNothing(item); + DoNothing.With(item); } } @@ -30,7 +32,7 @@ { foreach (var item in TestObjectsAsList) { - DoNothing(item); + DoNothing.With(item); } } @@ -38,7 +40,7 @@ { foreach (var item in TestObjectsAsPooledList) { - DoNothing(item); + DoNothing.With(item); } } @@ -46,7 +48,7 @@ { foreach (var item in TestObjectsAsPooledList) { - DoNothing(item); + DoNothing.With(item); } } @@ -54,15 +56,15 @@ { foreach (var item in TestObjectsAsRecyclableList) { - DoNothing(item); + DoNothing.With(item); } } public void RecyclableList_VersionedForEach() { - foreach (var item in (IRecyclableVersionedList)TestObjectsAsRecyclableList) + foreach (var item in (IRecyclableVersionedList)TestObjectsAsRecyclableList) { - DoNothing(item); + DoNothing.With(item); } } @@ -70,15 +72,15 @@ { foreach (var item in TestObjectsAsRecyclableLongList) { - DoNothing(item); + DoNothing.With(item); } } public void RecyclableLongList_VersionedForEach() { - foreach (var item in (IRecyclableVersionedLongList)TestObjectsAsRecyclableLongList) + foreach (var item in (IRecyclableVersionedLongList)TestObjectsAsRecyclableLongList) { - DoNothing(item); + DoNothing.With(item); } } } diff --git a/Recyclable.Collections.Benchmarks/Benchmarks/GetItem..cs b/Recyclable.Collections.Benchmarks/Benchmarks/GetItem..cs index 4f03945..030897f 100644 --- a/Recyclable.Collections.Benchmarks/Benchmarks/GetItem..cs +++ b/Recyclable.Collections.Benchmarks/Benchmarks/GetItem..cs @@ -1,4 +1,6 @@ -namespace Recyclable.Collections.Benchmarks +using Collections.Benchmarks.Core; + +namespace Recyclable.Collections.Benchmarks { public partial class RecyclableCollectionsBenchmarks { @@ -8,7 +10,7 @@ var dataCount = TestObjectCount; for (var i = 0; i < dataCount; i++) { - DoNothing(data[i]); + DoNothing.With(data[i]); } } @@ -18,7 +20,7 @@ var dataCount = TestObjectCount; for (var i = 0; i < dataCount; i++) { - DoNothing(data[i]); + DoNothing.With(data[i]); } } @@ -28,7 +30,7 @@ var dataCount = TestObjectCount; for (var i = 0; i < dataCount; i++) { - DoNothing(data[i]); + DoNothing.With(data[i]); } } @@ -38,7 +40,7 @@ var dataCount = TestObjectCount; for (var i = 0; i < dataCount; i++) { - DoNothing(data[i]); + DoNothing.With(data[i]); } } @@ -48,7 +50,7 @@ var dataCount = TestObjectCount; for (var i = 0; i < dataCount; i++) { - DoNothing(data[i]); + DoNothing.With(data[i]); } } @@ -64,7 +66,7 @@ var memoryBlock = new Span(memoryBlocks[blockIndex], 0, blockSize); for (var itemIndex = 0; itemIndex < blockSize; itemIndex++) { - DoNothing(memoryBlock[itemIndex]); + DoNothing.With(memoryBlock[itemIndex]); } } @@ -73,7 +75,7 @@ var memoryBlock = new Span(memoryBlocks[nextItemBlockIndex], 0, data.NextItemIndex); for (var itemIndex = 0; itemIndex < memoryBlock.Length; itemIndex++) { - DoNothing(memoryBlock[itemIndex]); + DoNothing.With(memoryBlock[itemIndex]); } } } @@ -90,7 +92,7 @@ var memoryBlock = memoryBlocks[blockIndex]; for (var itemIndex = 0; itemIndex < blockSize; itemIndex++) { - DoNothing(memoryBlock[itemIndex]); + DoNothing.With(memoryBlock[itemIndex]); } } @@ -100,7 +102,7 @@ blockSize = data.NextItemIndex; for (var itemIndex = 0; itemIndex < blockSize; itemIndex++) { - DoNothing(memoryBlock[itemIndex]); + DoNothing.With(memoryBlock[itemIndex]); } } } @@ -110,7 +112,7 @@ var data = TestObjectsAsRecyclableLongList; foreach (var item in data) { - DoNothing(item); + DoNothing.With(item); } } @@ -131,7 +133,7 @@ var memoryBlock = memoryBlocks[0]; while (blockIndex < nextItemBlockIndex) { - DoNothing(memoryBlock[itemIndex]); + DoNothing.With(memoryBlock[itemIndex]); if (itemIndex + 1 < blockSize) { itemIndex++; @@ -150,7 +152,7 @@ blockSize = data.NextItemIndex; while (itemIndex < blockSize) { - DoNothing(memoryBlock[itemIndex++]); + DoNothing.With(memoryBlock[itemIndex++]); } } } diff --git a/Recyclable.Collections.Benchmarks/Benchmarks/IndexOf_BestAndWorstCases.cs b/Recyclable.Collections.Benchmarks/Benchmarks/IndexOf_BestAndWorstCases.cs index e1d182c..092d56e 100644 --- a/Recyclable.Collections.Benchmarks/Benchmarks/IndexOf_BestAndWorstCases.cs +++ b/Recyclable.Collections.Benchmarks/Benchmarks/IndexOf_BestAndWorstCases.cs @@ -1,4 +1,6 @@ -namespace Recyclable.Collections.Benchmarks +using Collections.Benchmarks.Core; + +namespace Recyclable.Collections.Benchmarks { public partial class RecyclableCollectionsBenchmarks { @@ -9,8 +11,8 @@ var dataCount = TestObjectCountForSlowMethods; for (var i = 0; i < dataCount; i++) { - DoNothing(Array.IndexOf(list, data[i])); - DoNothing(Array.IndexOf(list, data[^(i + 1)])); + DoNothing.With(Array.IndexOf(list, data[i])); + DoNothing.With(Array.IndexOf(list, data[^(i + 1)])); } } @@ -21,8 +23,8 @@ var dataCount = TestObjectCountForSlowMethods; for (var i = 0; i < dataCount; i++) { - DoNothing(list.IndexOf(data[i])); - DoNothing(list.IndexOf(data[^(i + 1)])); + DoNothing.With(list.IndexOf(data[i])); + DoNothing.With(list.IndexOf(data[^(i + 1)])); } } @@ -33,8 +35,8 @@ var dataCount = TestObjectCountForSlowMethods; for (var i = 0; i < dataCount; i++) { - DoNothing(list.IndexOf(data[i])); - DoNothing(list.IndexOf(data[^(i + 1)])); + DoNothing.With(list.IndexOf(data[i])); + DoNothing.With(list.IndexOf(data[^(i + 1)])); } } @@ -45,8 +47,8 @@ var dataCount = TestObjectCountForSlowMethods; for (var i = 0; i < dataCount; i++) { - DoNothing(list.IndexOf(data[i])); - DoNothing(list.IndexOf(data[^(i + 1)])); + DoNothing.With(list.IndexOf(data[i])); + DoNothing.With(list.IndexOf(data[^(i + 1)])); } } @@ -57,8 +59,8 @@ var dataCount = TestObjectCountForSlowMethods; for (var i = 0; i < dataCount; i++) { - DoNothing(list.IndexOf(data[i])); - DoNothing(list.IndexOf(data[^(i + 1)])); + DoNothing.With(list.IndexOf(data[i])); + DoNothing.With(list.IndexOf(data[^(i + 1)])); } } @@ -69,8 +71,8 @@ var dataCount = TestObjectCountForSlowMethods; for (var i = 0; i < dataCount; i++) { - DoNothing(list.IndexOf(data[i])); - DoNothing(list.LongIndexOf(data[^(i + 1)])); + DoNothing.With(list.IndexOf(data[i])); + DoNothing.With(list.LongIndexOf(data[^(i + 1)])); } } } diff --git a/Recyclable.Collections.Benchmarks/Benchmarks/IndexOf_FirstItems.cs b/Recyclable.Collections.Benchmarks/Benchmarks/IndexOf_FirstItems.cs index f552702..e79089b 100644 --- a/Recyclable.Collections.Benchmarks/Benchmarks/IndexOf_FirstItems.cs +++ b/Recyclable.Collections.Benchmarks/Benchmarks/IndexOf_FirstItems.cs @@ -1,4 +1,6 @@ -namespace Recyclable.Collections.Benchmarks +using Collections.Benchmarks.Core; + +namespace Recyclable.Collections.Benchmarks { public partial class RecyclableCollectionsBenchmarks { @@ -9,7 +11,7 @@ var dataCount = TestObjectCountForSlowMethods; for (var i = 0; i < dataCount; i++) { - DoNothing(Array.IndexOf(list, data[i])); + DoNothing.With(Array.IndexOf(list, data[i])); } } @@ -20,7 +22,7 @@ var dataCount = TestObjectCountForSlowMethods; for (var i = 0; i < dataCount; i++) { - DoNothing(list.IndexOf(data[i])); + DoNothing.With(list.IndexOf(data[i])); } } @@ -31,7 +33,7 @@ var dataCount = TestObjectCountForSlowMethods; for (var i = 0; i < dataCount; i++) { - DoNothing(list.IndexOf(data[i])); + DoNothing.With(list.IndexOf(data[i])); } } @@ -42,7 +44,7 @@ var dataCount = TestObjectCountForSlowMethods; for (var i = 0; i < dataCount; i++) { - DoNothing(list.IndexOf(data[i])); + DoNothing.With(list.IndexOf(data[i])); } } @@ -53,7 +55,7 @@ var dataCount = TestObjectCountForSlowMethods; for (var i = 0; i < dataCount; i++) { - DoNothing(list.IndexOf(data[i])); + DoNothing.With(list.IndexOf(data[i])); } } @@ -64,7 +66,7 @@ var dataCount = TestObjectCountForSlowMethods; for (var i = 0; i < dataCount; i++) { - DoNothing(list.LongIndexOf(data[i])); + DoNothing.With(list.LongIndexOf(data[i])); } } } diff --git a/Recyclable.Collections.Benchmarks/Benchmarks/IndexOf_LastItems.cs b/Recyclable.Collections.Benchmarks/Benchmarks/IndexOf_LastItems.cs index 1b7681f..4034e11 100644 --- a/Recyclable.Collections.Benchmarks/Benchmarks/IndexOf_LastItems.cs +++ b/Recyclable.Collections.Benchmarks/Benchmarks/IndexOf_LastItems.cs @@ -1,4 +1,6 @@ -namespace Recyclable.Collections.Benchmarks +using Collections.Benchmarks.Core; + +namespace Recyclable.Collections.Benchmarks { public partial class RecyclableCollectionsBenchmarks { @@ -9,7 +11,7 @@ var dataCount = TestObjectCountForSlowMethods; for (var i = 0; i < dataCount; i++) { - DoNothing(Array.IndexOf(list, data[^(i + 1)])); + DoNothing.With(Array.IndexOf(list, data[^(i + 1)])); } } @@ -20,7 +22,7 @@ var dataCount = TestObjectCountForSlowMethods; for (var i = 0; i < dataCount; i++) { - DoNothing(list.IndexOf(data[^(i + 1)])); + DoNothing.With(list.IndexOf(data[^(i + 1)])); } } @@ -31,7 +33,7 @@ var dataCount = TestObjectCountForSlowMethods; for (var i = 0; i < dataCount; i++) { - DoNothing(list.IndexOf(data[^(i + 1)])); + DoNothing.With(list.IndexOf(data[^(i + 1)])); } } @@ -42,7 +44,7 @@ var dataCount = TestObjectCountForSlowMethods; for (var i = 0; i < dataCount; i++) { - DoNothing(list.IndexOf(data[^(i + 1)])); + DoNothing.With(list.IndexOf(data[^(i + 1)])); } } @@ -53,7 +55,7 @@ var dataCount = TestObjectCountForSlowMethods; for (var i = 0; i < dataCount; i++) { - DoNothing(list.IndexOf(data[^(i + 1)])); + DoNothing.With(list.IndexOf(data[^(i + 1)])); } } @@ -64,7 +66,7 @@ var dataCount = TestObjectCountForSlowMethods; for (var i = 0; i < dataCount; i++) { - DoNothing(list.LongIndexOf(data[^(i + 1)])); + DoNothing.With(list.LongIndexOf(data[^(i + 1)])); } } } diff --git a/Recyclable.Collections.Benchmarks/Benchmarks/LongCount.cs b/Recyclable.Collections.Benchmarks/Benchmarks/LongCount.cs index 9640ecd..90ba5de 100644 --- a/Recyclable.Collections.Benchmarks/Benchmarks/LongCount.cs +++ b/Recyclable.Collections.Benchmarks/Benchmarks/LongCount.cs @@ -1,17 +1,19 @@ -namespace Recyclable.Collections.Benchmarks +using Collections.Benchmarks.Core; + +namespace Recyclable.Collections.Benchmarks { public partial class RecyclableCollectionsBenchmarks { public void Array_LongCount() { var data = TestObjects; - DoNothing(data.LongLength); + DoNothing.With(data.LongLength); } public void RecyclableLongList_LongCount() { var data = TestObjectsAsRecyclableLongList; - DoNothing(data.LongCount); + DoNothing.With(data.LongCount); } } } diff --git a/Recyclable.Collections.Benchmarks/Benchmarks/RecyclableCollections.Benchmarks.cs b/Recyclable.Collections.Benchmarks/Benchmarks/RecyclableCollections.Benchmarks.cs index 55f0b46..2397c26 100644 --- a/Recyclable.Collections.Benchmarks/Benchmarks/RecyclableCollections.Benchmarks.cs +++ b/Recyclable.Collections.Benchmarks/Benchmarks/RecyclableCollections.Benchmarks.cs @@ -1,100 +1,115 @@ -using System.Reflection; -using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Attributes; +using Collections.Benchmarks.Core; namespace Recyclable.Collections.Benchmarks { - public enum RecyclableCollectionsBenchmarkType + public partial class RecyclableCollectionsBenchmarks : DataDrivenBenchmarksBase { - Unknown, Add_WithCapacity, Add, AddRange_WithCapacity, AddRangeWhenSourceIsArray, AddRangeWhenSourceIsIEnumerable, - AddRangeWhenSourceIsIList, AddRangeWhenSourceIsList, AddRangeWhenSourceIsSameType, BinarySearch_BestAndWorstCases, - Contains_FirstItems, Contains_LastItems, ConvertAll, Count, Create_WithCapacity, Create, Exists_BestAndWorstCases, - Find_BestAndWorstCases, FindAll_BestAndWorstCases, FindLast_BestAndWorstCases, FindLastIndex_BestAndWorstCases, - ForEach, GetItem, IndexOf_BestAndWorstCases,IndexOf_FirstItems, IndexOf_LastItems, LongCount, - Remove_FirstItems, Remove_LastItems, RemoveAt_FirstItems, RemoveAt_LastItems, - SetItem, VersionedForEach - } + protected override string GetTestMethodName(CollectionsBenchmarksSource benchmarkType) => TestCase switch + { + CollectionsBenchmarkType.AddRangeWhenSourceIsSameType => $"{benchmarkType}_AddRangeWhenSourceIs{benchmarkType}", + _ => $"{benchmarkType}_{TestCase}" + }; - public partial class RecyclableCollectionsBenchmarks : RecyclableBenchmarkBase - { public RecyclableCollectionsBenchmarks() { TestObjectCount = 1; - //BaseDataType = RecyclableCollectionsBenchmarkSource.List; - DataType = RecyclableCollectionsBenchmarkSource.RecyclableList; + //BaseDataType = RecyclableCollectionsBenchmarksSource.List; + DataType = CollectionsBenchmarksSource.RecyclableList; } - [Params - ( - RecyclableCollectionsBenchmarkType.Add_WithCapacity, - RecyclableCollectionsBenchmarkType.Add, - RecyclableCollectionsBenchmarkType.AddRange_WithCapacity, - RecyclableCollectionsBenchmarkType.AddRangeWhenSourceIsArray, - RecyclableCollectionsBenchmarkType.AddRangeWhenSourceIsIEnumerable, - RecyclableCollectionsBenchmarkType.AddRangeWhenSourceIsIList, - RecyclableCollectionsBenchmarkType.AddRangeWhenSourceIsList, - RecyclableCollectionsBenchmarkType.AddRangeWhenSourceIsSameType, - RecyclableCollectionsBenchmarkType.BinarySearch_BestAndWorstCases, - RecyclableCollectionsBenchmarkType.Contains_FirstItems, - RecyclableCollectionsBenchmarkType.Contains_LastItems, - RecyclableCollectionsBenchmarkType.ConvertAll, - RecyclableCollectionsBenchmarkType.Count, - RecyclableCollectionsBenchmarkType.Create_WithCapacity, - RecyclableCollectionsBenchmarkType.Create, - RecyclableCollectionsBenchmarkType.Exists_BestAndWorstCases, - RecyclableCollectionsBenchmarkType.Find_BestAndWorstCases, - RecyclableCollectionsBenchmarkType.FindAll_BestAndWorstCases, - RecyclableCollectionsBenchmarkType.FindLast_BestAndWorstCases, - RecyclableCollectionsBenchmarkType.FindLastIndex_BestAndWorstCases, - RecyclableCollectionsBenchmarkType.ForEach, - RecyclableCollectionsBenchmarkType.GetItem, - RecyclableCollectionsBenchmarkType.IndexOf_BestAndWorstCases, - RecyclableCollectionsBenchmarkType.IndexOf_FirstItems, - RecyclableCollectionsBenchmarkType.IndexOf_LastItems, - RecyclableCollectionsBenchmarkType.LongCount, - RecyclableCollectionsBenchmarkType.Remove_FirstItems, - RecyclableCollectionsBenchmarkType.Remove_LastItems, - RecyclableCollectionsBenchmarkType.RemoveAt_FirstItems, - RecyclableCollectionsBenchmarkType.RemoveAt_LastItems, - RecyclableCollectionsBenchmarkType.SetItem, - RecyclableCollectionsBenchmarkType.VersionedForEach - )] + // 0 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 32768 65536 131072 262144 524_288 + // 1048576 2097152 4194304 8388608 16777216 33554432 67108864 134217728 268435456 536870912 + // 1073741824 2147483648 - public RecyclableCollectionsBenchmarkType TestCase { get; set; } = RecyclableCollectionsBenchmarkType.IndexOf_BestAndWorstCases; + // [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 32, 40, 50, 60, 80, 90, 100, 128, 256, 512, 1024, 2048, 4096, 8192, 1_000_000)] + // [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 32, 40, 50, 60, 80, 90, 100, 128, 256, 512, 1024, 2048, 4096, 8192, 1_000_000)] + // [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 32, 40, 50, 60, 80, 90, 100, 128, 256, 512, 1024, 2048, 4096, 8192, 100_000_000)] + // [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 32, 40, 50, 60, 80, 90, 100, 128, 256, 512, 1024, 2048, 4096, 8192, 850_000 - 1, 1_000_000, RecyclableDefaults.MaxPooledBlockSize)] + // [Params(1_000_000, 10_000_000, 100_000_000, 1_000_000_000)] + // [Params(1, 10, 64, 128, 192, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144)] + // [Params(524_288, 786_432, 1_048_576)] + // [Params(262_144, 393_216, 524_288)] + // [Params(850_000_000)] + // [Params(100_000_000)] + // [Params(RecyclableDefaults.MinItemsCountForParallelization)] + [Params(16_384)] + // [Params(127)] + // [Params(16)] + // [Params(10, 15, 128)] + // [Params(1)] + // [Params(RecyclableDefaults.MaxPooledBlockSize)] + // [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 32, 40, 50, 60, 80, 90, 100, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 10_000_000, 33_554_432, 50_000_000, 100_000_000)] + // *** [Params(RecyclableDefaults.MinPooledArrayLength - 3, RecyclableDefaults.MinPooledArrayLength - 2, RecyclableDefaults.MinPooledArrayLength - 1, RecyclableDefaults.MinPooledArrayLength, RecyclableDefaults.MinPooledArrayLength + 1, RecyclableDefaults.MinPooledArrayLength + 2, RecyclableDefaults.MinPooledArrayLength + 3)] + // *** [Params(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 32, 40, RecyclableDefaults.MinPooledArrayLength - 1, RecyclableDefaults.MinPooledArrayLength, 40, 50, 60, 70, 80, 90, 100, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, RecyclableDefaults.MinItemsCountForParallelization)] + // *** [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 32, 40, RecyclableDefaults.MinPooledArrayLength - 1, RecyclableDefaults.MinPooledArrayLength, 40, 50, 60, 70, 80, 90, 100, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, RecyclableDefaults.MinItemsCountForParallelization)] + // [Params(256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, RecyclableDefaults.MinItemsCountForParallelization)] + // [Params(RecyclableDefaults.MinItemsCountForParallelization, 1_048_576, 2_097_152, 4_194_304, 8_388_608, 16_777_216, 33_554_432, RecyclableDefaults.MaxPooledBlockSize)] + // *** [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, RecyclableDefaults.MinPooledArrayLength - 1, RecyclableDefaults.MinPooledArrayLength, 40, 50, 60, 64, 70, 80, 90, 100, 127, 128)] + // [Params(1, 10, 1024, 10240, RecyclableDefaults.MinPooledArrayLength, RecyclableDefaults.MinItemsCountForParallelization)] + // [Params(RecyclableDefaults.MinItemsCountForParallelization * 3)] + // [Params(1_048_576)] + public override int TestObjectCount { get => base.TestObjectCount; set => base.TestObjectCount = value; } [Params ( - RecyclableCollectionsBenchmarkSource.List + CollectionsBenchmarksSource.Array, + CollectionsBenchmarksSource.List, + CollectionsBenchmarksSource.PooledList, + CollectionsBenchmarksSource.RecyclableList, + CollectionsBenchmarksSource.RecyclableLongList )] - public override RecyclableCollectionsBenchmarkSource BaseDataType { get => base.BaseDataType; set => base.BaseDataType = value; } + public override CollectionsBenchmarksSource DataType { get => base.DataType; set => base.DataType = value; } [Params ( - RecyclableCollectionsBenchmarkSource.Array, - RecyclableCollectionsBenchmarkSource.List, - RecyclableCollectionsBenchmarkSource.PooledList, - RecyclableCollectionsBenchmarkSource.RecyclableList, - RecyclableCollectionsBenchmarkSource.RecyclableLongList + CollectionsBenchmarkType.Add_WithCapacity, + CollectionsBenchmarkType.Add, + CollectionsBenchmarkType.AddRange_WithCapacity, + CollectionsBenchmarkType.AddRangeWhenSourceIsArray, + CollectionsBenchmarkType.AddRangeWhenSourceIsIEnumerable, + CollectionsBenchmarkType.AddRangeWhenSourceIsIList, + CollectionsBenchmarkType.AddRangeWhenSourceIsList, + CollectionsBenchmarkType.AddRangeWhenSourceIsSameType, + CollectionsBenchmarkType.BinarySearch_BestAndWorstCases, + CollectionsBenchmarkType.Contains_FirstItems, + CollectionsBenchmarkType.Contains_LastItems, + CollectionsBenchmarkType.ConvertAll, + CollectionsBenchmarkType.Count, + CollectionsBenchmarkType.Create_WithCapacity, + CollectionsBenchmarkType.Create, + CollectionsBenchmarkType.Exists_BestAndWorstCases, + CollectionsBenchmarkType.Find_BestAndWorstCases, + CollectionsBenchmarkType.FindAll_BestAndWorstCases, + CollectionsBenchmarkType.FindLast_BestAndWorstCases, + CollectionsBenchmarkType.FindLastIndex_BestAndWorstCases, + CollectionsBenchmarkType.ForEach, + CollectionsBenchmarkType.GetItem, + CollectionsBenchmarkType.IndexOf_BestAndWorstCases, + CollectionsBenchmarkType.IndexOf_FirstItems, + CollectionsBenchmarkType.IndexOf_LastItems, + CollectionsBenchmarkType.LongCount, + CollectionsBenchmarkType.Remove_FirstItems, + CollectionsBenchmarkType.Remove_LastItems, + CollectionsBenchmarkType.RemoveAt_FirstItems, + CollectionsBenchmarkType.RemoveAt_LastItems, + CollectionsBenchmarkType.SetItem, + CollectionsBenchmarkType.VersionedForEach )] - public override RecyclableCollectionsBenchmarkSource DataType { get => base.DataType; set => base.DataType = value; } - protected override Action? GetTestMethod(RecyclableCollectionsBenchmarkSource benchmarkType) - => TestCase switch - { - RecyclableCollectionsBenchmarkType.AddRangeWhenSourceIsSameType => (Action?)GetType().GetMethod($"{benchmarkType}_AddRangeWhenSourceIs{benchmarkType}", BindingFlags.Instance | BindingFlags.Public)?.CreateDelegate(typeof(Action), this), - _ => (Action?) GetType().GetMethod($"{benchmarkType}_{TestCase}", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public)?.CreateDelegate(typeof(Action), this) ?? throw new InvalidOperationException($"Method {benchmarkType}_{TestCase} not found in class {GetType().FullName}") - }; + public virtual CollectionsBenchmarkType TestCase { get; set; } public override void Setup() { base.Setup(); switch(TestCase) { - case RecyclableCollectionsBenchmarkType.AddRangeWhenSourceIsIList: - PrepareData(RecyclableCollectionsBenchmarkSource.RecyclableLongList); + case CollectionsBenchmarkType.AddRangeWhenSourceIsIList: + PrepareData(CollectionsBenchmarksSource.RecyclableLongList); break; - case RecyclableCollectionsBenchmarkType.AddRangeWhenSourceIsSameType: - PrepareData(RecyclableCollectionsBenchmarkSource.RecyclableList); + case CollectionsBenchmarkType.AddRangeWhenSourceIsSameType: + PrepareData(CollectionsBenchmarksSource.RecyclableList); break; } } diff --git a/Recyclable.Collections.Benchmarks/Benchmarks/Remove_FirstItems.cs b/Recyclable.Collections.Benchmarks/Benchmarks/Remove_FirstItems.cs index 1640951..5637a05 100644 --- a/Recyclable.Collections.Benchmarks/Benchmarks/Remove_FirstItems.cs +++ b/Recyclable.Collections.Benchmarks/Benchmarks/Remove_FirstItems.cs @@ -1,4 +1,5 @@ using Collections.Pooled; +using Collections.Benchmarks.Core; namespace Recyclable.Collections.Benchmarks { @@ -11,7 +12,7 @@ namespace Recyclable.Collections.Benchmarks var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount; for (var i = 0; i < dataCount; i++) { - DoNothing(list.Remove(data[i])); + DoNothing.With(list.Remove(data[i])); } } @@ -22,7 +23,7 @@ namespace Recyclable.Collections.Benchmarks var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount; for (var i = 0; i < dataCount; i++) { - DoNothing(list.Remove(data[i])); + DoNothing.With(list.Remove(data[i])); } } @@ -33,7 +34,7 @@ namespace Recyclable.Collections.Benchmarks var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount; for (var i = 0; i < dataCount; i++) { - DoNothing(list.Remove(data[i])); + DoNothing.With(list.Remove(data[i])); } } @@ -44,7 +45,7 @@ namespace Recyclable.Collections.Benchmarks var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount; for (var i = 0; i < dataCount; i++) { - DoNothing(list.Remove(data[i])); + DoNothing.With(list.Remove(data[i])); } } } diff --git a/Recyclable.Collections.Benchmarks/Benchmarks/Remove_LastItems.cs b/Recyclable.Collections.Benchmarks/Benchmarks/Remove_LastItems.cs index d971c7a..ec05cab 100644 --- a/Recyclable.Collections.Benchmarks/Benchmarks/Remove_LastItems.cs +++ b/Recyclable.Collections.Benchmarks/Benchmarks/Remove_LastItems.cs @@ -1,4 +1,5 @@ using Collections.Pooled; +using Collections.Benchmarks.Core; namespace Recyclable.Collections.Benchmarks { @@ -11,7 +12,7 @@ namespace Recyclable.Collections.Benchmarks var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount; for (var i = data.Length - 1; i > data.Length - dataCount - 1; i--) { - DoNothing(list.Remove(data[i])); + DoNothing.With(list.Remove(data[i])); } } @@ -22,7 +23,7 @@ namespace Recyclable.Collections.Benchmarks var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount; for (var i = data.Length - 1; i > data.Length - dataCount - 1; i--) { - DoNothing(list.Remove(data[i])); + DoNothing.With(list.Remove(data[i])); } } @@ -33,7 +34,7 @@ namespace Recyclable.Collections.Benchmarks var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount; for (var i = data.Length - 1; i > data.Length - dataCount - 1; i--) { - DoNothing(list.Remove(data[i])); + DoNothing.With(list.Remove(data[i])); } } @@ -44,7 +45,7 @@ namespace Recyclable.Collections.Benchmarks var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount; for (var i = data.Length - 1; i > data.Length - dataCount - 1; i--) { - DoNothing(list.Remove(data[i])); + DoNothing.With(list.Remove(data[i])); } } } diff --git a/Recyclable.Collections.Benchmarks/Core/DataGenerator.cs b/Recyclable.Collections.Benchmarks/Core/DataGenerator.cs deleted file mode 100644 index faaaf4e..0000000 --- a/Recyclable.Collections.Benchmarks/Core/DataGenerator.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace Recyclable.Collections.Benchmarks.Core -{ - public static class DataGenerator - { - public static long[] EnumerateTestObjects(long testObjectCount) - { - var result = new long[testObjectCount]; - Console.WriteLine("******* TEST DATA ARRAY CREATED *******"); - - Span resultSpan = result; - for (int i = 0; i < testObjectCount; i++) - { - resultSpan[i] = i; - } - - return result; - } - } -} \ No newline at end of file diff --git a/Recyclable.Collections.Benchmarks/POC/ArraySizeLimitPoc.Benchmarks.cs b/Recyclable.Collections.Benchmarks/POC/ArraySizeLimitBenchmarks.cs similarity index 82% rename from Recyclable.Collections.Benchmarks/POC/ArraySizeLimitPoc.Benchmarks.cs rename to Recyclable.Collections.Benchmarks/POC/ArraySizeLimitBenchmarks.cs index e46231a..29b5532 100644 --- a/Recyclable.Collections.Benchmarks/POC/ArraySizeLimitPoc.Benchmarks.cs +++ b/Recyclable.Collections.Benchmarks/POC/ArraySizeLimitBenchmarks.cs @@ -1,18 +1,21 @@ -using BenchmarkDotNet.Attributes; +// Ignore Spelling: Poc + +using BenchmarkDotNet.Attributes; +using Collections.Benchmarks.Core; using System.Buffers; namespace Recyclable.Collections.Benchmarks.POC { - public enum ArraySizeLimitPocBenchmarkType + public enum ArraySizeLimitBenchmarkType { ArraySizeLimit } - public class ArraySizeLimitPocBenchmarks : PocBenchmarkBase + public class ArraySizeLimitBenchmarks : BaselineVsActualBenchmarkBase { public static void Run() { - var benchmark = new ArraySizeLimitPocBenchmarks(); + var benchmark = new ArraySizeLimitBenchmarks(); benchmark.Setup(); FindArraySizeLimit(); benchmark.Cleanup(); @@ -25,7 +28,7 @@ namespace Recyclable.Collections.Benchmarks.POC public void Max_Allowed_Size_2_147_483_605() { long[] arr = ArrayPool.Shared.Rent(TestObjectCount); - DoNothing(arr); + DoNothing.With(arr); } [Benchmark(OperationsPerInvoke = 1)] diff --git a/Recyclable.Collections.Benchmarks/POC/BoolOrCompareBenchmarks.cs b/Recyclable.Collections.Benchmarks/POC/BoolOrCompareBenchmarks.cs new file mode 100644 index 0000000..59441ec --- /dev/null +++ b/Recyclable.Collections.Benchmarks/POC/BoolOrCompareBenchmarks.cs @@ -0,0 +1,66 @@ +// Ignore Spelling: Poc + +using BenchmarkDotNet.Attributes; +using Collections.Benchmarks.Core; + +namespace Recyclable.Collections.Benchmarks.POC +{ + public enum BoolOrCompareBenchmarkType + { + Bool, + Compare, + } + + [MemoryDiagnoser] + public class BoolOrCompareBenchmarks : BaselineVsActualBenchmarkBase + { + [Params(BoolOrCompareBenchmarkType.Bool, BoolOrCompareBenchmarkType.Compare)] + public override BoolOrCompareBenchmarkType DataType { get => base.DataType; set => base.DataType = value; } + + [Params(8)] + public override int TestObjectCount { get => base.TestObjectCount; set => base.TestObjectCount = value; } + + [Params(true)] + public bool TestBool = true; + + public static void Run() + { + var benchmark = new BoolOrCompareBenchmarks(); + benchmark.Setup(); + benchmark.Bool(); + benchmark.Compare(); + benchmark.Cleanup(); + } + + public void Bool() + { + if (TestBool) + { + DoNothing.With(TestBool); + } + else + { + DoNothing.With(TestBool); + } + } + + public void Compare() + { + if (TestObjectCount >= RecyclableDefaults.MinPooledArrayLength) + { + DoNothing.With(TestBool); + } + else + { + DoNothing.With(TestBool); + } + } + + protected override Action? GetTestMethod(BoolOrCompareBenchmarkType benchmarkType) => benchmarkType switch + { + BoolOrCompareBenchmarkType.Bool => Bool, + BoolOrCompareBenchmarkType.Compare => Compare, + _ => throw CreateUnknownBenchmarkTypeException(benchmarkType), + }; + } +} \ No newline at end of file diff --git a/Recyclable.Collections.Benchmarks/POC/BoolOrComparePoc.Benchmarks.cs b/Recyclable.Collections.Benchmarks/POC/BoolOrComparePoc.Benchmarks.cs deleted file mode 100644 index 755b2a0..0000000 --- a/Recyclable.Collections.Benchmarks/POC/BoolOrComparePoc.Benchmarks.cs +++ /dev/null @@ -1,63 +0,0 @@ -using BenchmarkDotNet.Attributes; - -namespace Recyclable.Collections.Benchmarks.POC -{ - public enum BoolOrComparePocBenchmarkType - { - Bool, - Compare, - } - - [MemoryDiagnoser] - public class BoolOrComparePocBenchmarks : PocBenchmarkBase - { - [Params(BoolOrComparePocBenchmarkType.Bool, BoolOrComparePocBenchmarkType.Compare)] - public override BoolOrComparePocBenchmarkType DataType { get => base.DataType; set => base.DataType = value; } - - [Params(8)] - public override int TestObjectCount { get => base.TestObjectCount; set => base.TestObjectCount = value; } - - [Params(true)] - public bool TestBool = true; - - public static void Run() - { - var benchmark = new BoolOrComparePocBenchmarks(); - benchmark.Setup(); - benchmark.Bool(); - benchmark.Compare(); - benchmark.Cleanup(); - } - - public void Bool() - { - if (TestBool) - { - DoNothing(TestBool); - } - else - { - DoNothing(TestBool); - } - } - - public void Compare() - { - if (TestObjectCount >= RecyclableDefaults.MinPooledArrayLength) - { - DoNothing(TestBool); - } - else - { - DoNothing(TestBool); - } - } - - protected override Action? GetTestMethod(BoolOrComparePocBenchmarkType benchmarkType) => benchmarkType switch - { - BoolOrComparePocBenchmarkType.Bool => Bool, - BoolOrComparePocBenchmarkType.Compare => Compare, - _ => throw CreateUnknownBenchmarkTypeException(benchmarkType), - }; - } -} \ No newline at end of file diff --git a/Recyclable.Collections.Benchmarks/POC/DelegateVsComparerBenchmarks.cs b/Recyclable.Collections.Benchmarks/POC/DelegateVsComparerBenchmarks.cs new file mode 100644 index 0000000..2e14bb3 --- /dev/null +++ b/Recyclable.Collections.Benchmarks/POC/DelegateVsComparerBenchmarks.cs @@ -0,0 +1,349 @@ +// Ignore Spelling: Poc Structs Unboxed Funcs Comparers + +using BenchmarkDotNet.Attributes; +using Collections.Benchmarks.Core; + +namespace Recyclable.Collections.Benchmarks.POC +{ + public enum DelegateVsComparerBenchmarkType + { + Comparer, + Delegate, + Func, + ListOfBoxedStructs, + ListOfClasses, + ListOfComparers, + ListOfDelegates, + ListOfFuncs, + ListOfLocalFuncs, + ListOfStructs, + ListOfUnboxedReadOnlyStructs, + ListOfUnboxedStructs, + StaticFunc, + } + + [MemoryDiagnoser] + public class DelegateVsComparerBenchmarks : BaselineVsActualBenchmarkBase + { + [Params + ( + DelegateVsComparerBenchmarkType.Delegate, + DelegateVsComparerBenchmarkType.Func, + DelegateVsComparerBenchmarkType.ListOfBoxedStructs, + DelegateVsComparerBenchmarkType.ListOfClasses, + DelegateVsComparerBenchmarkType.ListOfComparers, + DelegateVsComparerBenchmarkType.ListOfDelegates, + DelegateVsComparerBenchmarkType.ListOfFuncs, + DelegateVsComparerBenchmarkType.ListOfLocalFuncs, + DelegateVsComparerBenchmarkType.ListOfStructs, + DelegateVsComparerBenchmarkType.ListOfUnboxedReadOnlyStructs, + DelegateVsComparerBenchmarkType.ListOfUnboxedStructs, + DelegateVsComparerBenchmarkType.StaticFunc + )] + public override DelegateVsComparerBenchmarkType DataType { get => base.DataType; set => base.DataType = value; } + + [Params(DelegateVsComparerBenchmarkType.Comparer)] + public override DelegateVsComparerBenchmarkType BaseDataType { get => base.BaseDataType; set => base.BaseDataType = value; } + + #region Dummy classes + + private delegate T Compare(T x, T y); + + public readonly struct MyComparerReadOnlyStruct : IComparer + { + public int Compare(T? x, T? y) => Comparer.Default.Compare(x, y); + } + + private struct MyComparerStruct : IComparer + { + public readonly int Compare(T? x, T? y) => Comparer.Default.Compare(x, y); + } + + private class MyComparer : IComparer + { + public int Compare(long x, long y) => (x - y) switch + { + > 0 => 1, + < 0 => -1, + _ => 0, + }; + } + + #endregion + + public static void Run() + { + var benchmark = new DelegateVsComparerBenchmarks(); + benchmark.Setup(); + benchmark.Comparer(); + benchmark.Delegate(); + benchmark.Func(); + benchmark.ListOfBoxedStructs(); + benchmark.ListOfClasses(); + benchmark.ListOfComparers(); + benchmark.ListOfDelegates(); + benchmark.ListOfFuncs(); + benchmark.ListOfLocalFuncs(); + benchmark.ListOfStructs(); + benchmark.ListOfUnboxedReadOnlyStructs(); + benchmark.ListOfUnboxedStructs(); + benchmark.StaticFunc(); + benchmark.Cleanup(); + } + + private static readonly Comparer _comparer = Comparer.Default; + private IEnumerable? _testObjects; + private IEnumerable>? _testListOfFunctions; + private IEnumerable>? _testListOfComparers; + private IEnumerable>? _testListOfDelegates; + private IEnumerable>? _testListOfLocalFunctions; + private IEnumerable? _testListOfClasses; + private IEnumerable>? _testListOfStructs; + private IEnumerable>? _testListOfBoxedStructs; + private IEnumerable TestListOfUnboxedStructs() where TComparer : IComparer, new() + { + foreach (var _ in _testObjects!) + { + yield return new TComparer(); + } + } + + private static IEnumerable> GetLocalFunctions(IEnumerable testObjects) + { + static int compareFunc(long x, long y) + { + return (x - y) switch + { + > 0 => 1, + < 0 => -1, + _ => 0 + }; + } + + foreach (var _ in testObjects) + { + yield return compareFunc; + } + } + + private void TestWithComparer(IComparer comparer) + { + var testData = _testObjects!.ToArray(); + for (var itemIdx = 0; itemIdx < testData.Length - 1; itemIdx++) + { + _ = comparer.Compare(testData[itemIdx], testData[itemIdx + 1]); + } + } + + private void TestWithDelegate(Compare compareFunc) + { + var testData = _testObjects!.ToArray(); + for (var itemIdx = 0; itemIdx < testData.Length - 1; itemIdx++) + { + _ = compareFunc(testData[itemIdx], testData[itemIdx + 1]); + } + } + + private void TestWithFunc(Func compareFunc) + { + var testData = _testObjects!.ToArray(); + for (var itemIdx = 0; itemIdx < testData.Length - 1; itemIdx++) + { + _ = compareFunc(testData[itemIdx], testData[itemIdx + 1]); + } + } + + public void Comparer() + { + TestWithComparer(_comparer); + } + + public void Func() + { + TestWithFunc((x, y) => (x - y) switch + { + > 0 => 1, + < 0 => -1, + _ => 0 + }); + } + + public void StaticFunc() + { + TestWithFunc(static (x, y) => (x - y) switch + { + > 0 => 1, + < 0 => -1, + _ => 0 + }); + } + + public void Delegate() + { + TestWithDelegate((x, y) => (x - y) switch + { + > 0 => 1, + < 0 => -1, + _ => 0 + }); + } + + public void ListOfFuncs() + { + const long X = 2, Y = 5; + var testData = _testListOfFunctions!.ToArray(); + for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++) + { + var compareFunc = testData[itemIdx]; + _ = compareFunc(X, Y); + } + } + + public void ListOfLocalFuncs() + { + const long X = 2, Y = 5; + var testData = _testListOfLocalFunctions!.ToArray(); + for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++) + { + var compareFunc = testData[itemIdx]; + _ = compareFunc(X, Y); + } + } + + public void ListOfComparers() + { + const long X = 2, Y = 5; + var testData = _testListOfComparers!.ToArray(); + for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++) + { + var comparer = testData[itemIdx]; + _ = comparer.Compare(X, Y); + } + } + + public void ListOfClasses() + { + const long X = 2, Y = 5; + var testData = _testListOfClasses!.ToArray(); + for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++) + { + var comparer = testData[itemIdx]; + _ = comparer.Compare(X, Y); + } + } + + public void ListOfStructs() + { + const long X = 2, Y = 5; + var testData = _testListOfStructs!.ToArray(); + for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++) + { + var comparer = testData[itemIdx]; + _ = comparer.Compare(X, Y); + } + } + + public void ListOfBoxedStructs() + { + const long X = 2, Y = 5; + var testData = _testListOfBoxedStructs!.ToArray(); + for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++) + { + var comparer = testData[itemIdx]; + _ = comparer.Compare(X, Y); + } + } + + public void ListOfUnboxedStructs() + { + const long X = 2, Y = 5; + var testData = TestListOfUnboxedStructs, long>().ToArray(); + for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++) + { + var comparer = testData[itemIdx]; + _ = comparer.Compare(X, Y); + } + } + + public void ListOfUnboxedReadOnlyStructs() + { + const long X = 2, Y = 5; + var testData = TestListOfUnboxedStructs, long>().ToArray(); + for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++) + { + var comparer = testData[itemIdx]; + _ = comparer.Compare(X, Y); + } + } + + public void ListOfDelegates() + { + const long X = 2, Y = 5; + var testData = _testListOfDelegates!.ToArray(); + for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++) + { + var compareDelegate = testData[itemIdx]; + _ = compareDelegate(X, Y); + } + } + + protected override Action? GetTestMethod(DelegateVsComparerBenchmarkType benchmarkType) => benchmarkType switch + { + DelegateVsComparerBenchmarkType.Comparer => Comparer, + DelegateVsComparerBenchmarkType.Delegate => Delegate, + DelegateVsComparerBenchmarkType.Func => Func, + DelegateVsComparerBenchmarkType.ListOfBoxedStructs => ListOfBoxedStructs, + DelegateVsComparerBenchmarkType.ListOfClasses => ListOfClasses, + DelegateVsComparerBenchmarkType.ListOfComparers => ListOfComparers, + DelegateVsComparerBenchmarkType.ListOfDelegates => ListOfDelegates, + DelegateVsComparerBenchmarkType.ListOfFuncs => ListOfFuncs, + DelegateVsComparerBenchmarkType.ListOfLocalFuncs => ListOfLocalFuncs, + DelegateVsComparerBenchmarkType.ListOfStructs => ListOfStructs, + DelegateVsComparerBenchmarkType.ListOfUnboxedReadOnlyStructs => ListOfUnboxedReadOnlyStructs, + DelegateVsComparerBenchmarkType.ListOfUnboxedStructs => ListOfUnboxedStructs, + DelegateVsComparerBenchmarkType.StaticFunc => StaticFunc, + _ => throw CreateUnknownBenchmarkTypeException(benchmarkType), + }; + + public override void Setup() + { + Console.WriteLine("******* SETTING UP COMMON TEST DATA *******"); + _testObjects = Enumerable.Range(1, TestObjectCount).Select(x => (long)x); + base.Setup(); + } + + public override void Cleanup() + { + _testObjects = null; + base.Cleanup(); + } + + protected override void PrepareData(T benchmarkType) + { + switch (benchmarkType) + { + case DelegateVsComparerBenchmarkType.ListOfBoxedStructs: + _testListOfBoxedStructs = _testObjects!.Select(_ => (IComparer)new MyComparerStruct()); + break; + case DelegateVsComparerBenchmarkType.ListOfClasses: + _testListOfClasses = _testObjects!.Select(_ => new MyComparer()); + break; + case DelegateVsComparerBenchmarkType.ListOfComparers: + _testListOfComparers = _testObjects!.Select(_ => (IComparer)new MyComparer()); + break; + case DelegateVsComparerBenchmarkType.ListOfDelegates: + _testListOfDelegates = _testObjects!.Select(_ => new Compare((x, y) => new MyComparer().Compare(x, y))); + break; + case DelegateVsComparerBenchmarkType.ListOfFuncs: + _testListOfFunctions = _testObjects!.Select>(static _ => new MyComparer().Compare); + break; + case DelegateVsComparerBenchmarkType.ListOfLocalFuncs: + _testListOfLocalFunctions = GetLocalFunctions(_testObjects!); + break; + case DelegateVsComparerBenchmarkType.ListOfStructs: + _testListOfStructs = _testObjects!.Select(_ => new MyComparerStruct()); + break; + } + } + } +} diff --git a/Recyclable.Collections.Benchmarks/POC/DelegateVsComparerPoc.Benchmarks.cs b/Recyclable.Collections.Benchmarks/POC/DelegateVsComparerPoc.Benchmarks.cs deleted file mode 100644 index fea010f..0000000 --- a/Recyclable.Collections.Benchmarks/POC/DelegateVsComparerPoc.Benchmarks.cs +++ /dev/null @@ -1,346 +0,0 @@ -using BenchmarkDotNet.Attributes; - -namespace Recyclable.Collections.Benchmarks.POC -{ - public enum DelegateVsComparerPocBenchmarkType - { - Comparer, - Delegate, - Func, - ListOfBoxedStructs, - ListOfClasses, - ListOfComparers, - ListOfDelegates, - ListOfFuncs, - ListOfLocalFuncs, - ListOfStructs, - ListOfUnboxedReadOnlyStructs, - ListOfUnboxedStructs, - StaticFunc, - } - - [MemoryDiagnoser] - public class DelegateVsComparerPocBenchmarks : PocBenchmarkBase - { - [Params - ( - DelegateVsComparerPocBenchmarkType.Delegate, - DelegateVsComparerPocBenchmarkType.Func, - DelegateVsComparerPocBenchmarkType.ListOfBoxedStructs, - DelegateVsComparerPocBenchmarkType.ListOfClasses, - DelegateVsComparerPocBenchmarkType.ListOfComparers, - DelegateVsComparerPocBenchmarkType.ListOfDelegates, - DelegateVsComparerPocBenchmarkType.ListOfFuncs, - DelegateVsComparerPocBenchmarkType.ListOfLocalFuncs, - DelegateVsComparerPocBenchmarkType.ListOfStructs, - DelegateVsComparerPocBenchmarkType.ListOfUnboxedReadOnlyStructs, - DelegateVsComparerPocBenchmarkType.ListOfUnboxedStructs, - DelegateVsComparerPocBenchmarkType.StaticFunc - )] - public override DelegateVsComparerPocBenchmarkType DataType { get => base.DataType; set => base.DataType = value; } - - [Params(DelegateVsComparerPocBenchmarkType.Comparer)] - public override DelegateVsComparerPocBenchmarkType BaseDataType { get => base.BaseDataType; set => base.BaseDataType = value; } - - #region Dummy classes - - private delegate T Compare(T x, T y); - - public readonly struct MyComparerReadOnlyStruct : IComparer - { - public int Compare(T? x, T? y) => Comparer.Default.Compare(x, y); - } - - private struct MyComparerStruct : IComparer - { - public readonly int Compare(T? x, T? y) => Comparer.Default.Compare(x, y); - } - - private class MyComparer : IComparer - { - public int Compare(long x, long y) => (x - y) switch - { - > 0 => 1, - < 0 => -1, - _ => 0, - }; - } - - #endregion - - public static void Run() - { - var benchmark = new DelegateVsComparerPocBenchmarks(); - benchmark.Setup(); - benchmark.Comparer(); - benchmark.Delegate(); - benchmark.Func(); - benchmark.ListOfBoxedStructs(); - benchmark.ListOfClasses(); - benchmark.ListOfComparers(); - benchmark.ListOfDelegates(); - benchmark.ListOfFuncs(); - benchmark.ListOfLocalFuncs(); - benchmark.ListOfStructs(); - benchmark.ListOfUnboxedReadOnlyStructs(); - benchmark.ListOfUnboxedStructs(); - benchmark.StaticFunc(); - benchmark.Cleanup(); - } - - private static readonly Comparer _comparer = Comparer.Default; - private IEnumerable? _testObjects; - private IEnumerable>? _testListOfFunctions; - private IEnumerable>? _testListOfComparers; - private IEnumerable>? _testListOfDelegates; - private IEnumerable>? _testListOfLocalFunctions; - private IEnumerable? _testListOfClasses; - private IEnumerable>? _testListOfStructs; - private IEnumerable>? _testListOfBoxedStructs; - private IEnumerable TestListOfUnboxedStructs() where TComparer : IComparer, new() - { - foreach (var _ in _testObjects!) - { - yield return new TComparer(); - } - } - - private static IEnumerable> GetLocalFunctions(IEnumerable testObjects) - { - static int compareFunc(long x, long y) - { - return (x - y) switch - { - > 0 => 1, - < 0 => -1, - _ => 0 - }; - } - - foreach (var _ in testObjects) - { - yield return compareFunc; - } - } - - private void TestWithComparer(IComparer comparer) - { - var testData = _testObjects!.ToArray(); - for (var itemIdx = 0; itemIdx < testData.Length - 1; itemIdx++) - { - _ = comparer.Compare(testData[itemIdx], testData[itemIdx + 1]); - } - } - - private void TestWithDelegate(Compare compareFunc) - { - var testData = _testObjects!.ToArray(); - for (var itemIdx = 0; itemIdx < testData.Length - 1; itemIdx++) - { - _ = compareFunc(testData[itemIdx], testData[itemIdx + 1]); - } - } - - private void TestWithFunc(Func compareFunc) - { - var testData = _testObjects!.ToArray(); - for (var itemIdx = 0; itemIdx < testData.Length - 1; itemIdx++) - { - _ = compareFunc(testData[itemIdx], testData[itemIdx + 1]); - } - } - - public void Comparer() - { - TestWithComparer(_comparer); - } - - public void Func() - { - TestWithFunc((x, y) => (x - y) switch - { - > 0 => 1, - < 0 => -1, - _ => 0 - }); - } - - public void StaticFunc() - { - TestWithFunc(static (x, y) => (x - y) switch - { - > 0 => 1, - < 0 => -1, - _ => 0 - }); - } - - public void Delegate() - { - TestWithDelegate((x, y) => (x - y) switch - { - > 0 => 1, - < 0 => -1, - _ => 0 - }); - } - - public void ListOfFuncs() - { - const long x = 2, y = 5; - var testData = _testListOfFunctions!.ToArray(); - for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++) - { - var compareFunc = testData[itemIdx]; - _ = compareFunc(x, y); - } - } - - public void ListOfLocalFuncs() - { - const long x = 2, y = 5; - var testData = _testListOfLocalFunctions!.ToArray(); - for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++) - { - var compareFunc = testData[itemIdx]; - _ = compareFunc(x, y); - } - } - - public void ListOfComparers() - { - const long x = 2, y = 5; - var testData = _testListOfComparers!.ToArray(); - for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++) - { - var comparer = testData[itemIdx]; - _ = comparer.Compare(x, y); - } - } - - public void ListOfClasses() - { - const long x = 2, y = 5; - var testData = _testListOfClasses!.ToArray(); - for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++) - { - var comparer = testData[itemIdx]; - _ = comparer.Compare(x, y); - } - } - - public void ListOfStructs() - { - const long x = 2, y = 5; - var testData = _testListOfStructs!.ToArray(); - for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++) - { - var comparer = testData[itemIdx]; - _ = comparer.Compare(x, y); - } - } - - public void ListOfBoxedStructs() - { - const long x = 2, y = 5; - var testData = _testListOfBoxedStructs!.ToArray(); - for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++) - { - var comparer = testData[itemIdx]; - _ = comparer.Compare(x, y); - } - } - - public void ListOfUnboxedStructs() - { - const long x = 2, y = 5; - var testData = TestListOfUnboxedStructs, long>().ToArray(); - for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++) - { - var comparer = testData[itemIdx]; - _ = comparer.Compare(x, y); - } - } - - public void ListOfUnboxedReadOnlyStructs() - { - const long x = 2, y = 5; - var testData = TestListOfUnboxedStructs, long>().ToArray(); - for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++) - { - var comparer = testData[itemIdx]; - _ = comparer.Compare(x, y); - } - } - - public void ListOfDelegates() - { - const long x = 2, y = 5; - var testData = _testListOfDelegates!.ToArray(); - for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++) - { - var compareDelegate = testData[itemIdx]; - _ = compareDelegate(x, y); - } - } - - protected override Action? GetTestMethod(DelegateVsComparerPocBenchmarkType benchmarkType) => benchmarkType switch - { - DelegateVsComparerPocBenchmarkType.Comparer => Comparer, - DelegateVsComparerPocBenchmarkType.Delegate => Delegate, - DelegateVsComparerPocBenchmarkType.Func => Func, - DelegateVsComparerPocBenchmarkType.ListOfBoxedStructs => ListOfBoxedStructs, - DelegateVsComparerPocBenchmarkType.ListOfClasses => ListOfClasses, - DelegateVsComparerPocBenchmarkType.ListOfComparers => ListOfComparers, - DelegateVsComparerPocBenchmarkType.ListOfDelegates => ListOfDelegates, - DelegateVsComparerPocBenchmarkType.ListOfFuncs => ListOfFuncs, - DelegateVsComparerPocBenchmarkType.ListOfLocalFuncs => ListOfLocalFuncs, - DelegateVsComparerPocBenchmarkType.ListOfStructs => ListOfStructs, - DelegateVsComparerPocBenchmarkType.ListOfUnboxedReadOnlyStructs => ListOfUnboxedReadOnlyStructs, - DelegateVsComparerPocBenchmarkType.ListOfUnboxedStructs => ListOfUnboxedStructs, - DelegateVsComparerPocBenchmarkType.StaticFunc => StaticFunc, - _ => throw CreateUnknownBenchmarkTypeException(benchmarkType), - }; - - public override void Setup() - { - Console.WriteLine("******* SETTING UP COMMON TEST DATA *******"); - _testObjects = Enumerable.Range(1, TestObjectCount).Select(x => (long)x); - base.Setup(); - } - - public override void Cleanup() - { - _testObjects = null; - base.Cleanup(); - } - - protected override void PrepareData(T benchmarkType) - { - switch (benchmarkType) - { - case DelegateVsComparerPocBenchmarkType.ListOfBoxedStructs: - _testListOfBoxedStructs = _testObjects!.Select(_ => (IComparer)new MyComparerStruct()); - break; - case DelegateVsComparerPocBenchmarkType.ListOfClasses: - _testListOfClasses = _testObjects!.Select(_ => new MyComparer()); - break; - case DelegateVsComparerPocBenchmarkType.ListOfComparers: - _testListOfComparers = _testObjects!.Select(_ => (IComparer)new MyComparer()); - break; - case DelegateVsComparerPocBenchmarkType.ListOfDelegates: - _testListOfDelegates = _testObjects!.Select(_ => new Compare((x, y) => new MyComparer().Compare(x, y))); - break; - case DelegateVsComparerPocBenchmarkType.ListOfFuncs: - _testListOfFunctions = _testObjects!.Select>(static _ => new MyComparer().Compare); - break; - case DelegateVsComparerPocBenchmarkType.ListOfLocalFuncs: - _testListOfLocalFunctions = GetLocalFunctions(_testObjects!); - break; - case DelegateVsComparerPocBenchmarkType.ListOfStructs: - _testListOfStructs = _testObjects!.Select(_ => new MyComparerStruct()); - break; - } - } - } -} diff --git a/Recyclable.Collections.Benchmarks/POC/EqualVsContainsInConsecutiveOrderBenchmarks.cs b/Recyclable.Collections.Benchmarks/POC/EqualVsContainsInConsecutiveOrderBenchmarks.cs index aaeab5b..5bc3541 100644 --- a/Recyclable.Collections.Benchmarks/POC/EqualVsContainsInConsecutiveOrderBenchmarks.cs +++ b/Recyclable.Collections.Benchmarks/POC/EqualVsContainsInConsecutiveOrderBenchmarks.cs @@ -2,7 +2,7 @@ using BenchmarkDotNet.Attributes; using FluentAssertions; -using Recyclable.CollectionsTests; +using Recyclable.Collections.TestData; namespace Recyclable.Collections.Benchmarks.POC { diff --git a/Recyclable.Collections.Benchmarks/POC/GreaterOperatorVsNotEqualOperatorBenchmarks.cs b/Recyclable.Collections.Benchmarks/POC/GreaterOperatorVsNotEqualOperatorBenchmarks.cs new file mode 100644 index 0000000..2bf5241 --- /dev/null +++ b/Recyclable.Collections.Benchmarks/POC/GreaterOperatorVsNotEqualOperatorBenchmarks.cs @@ -0,0 +1,50 @@ +// Ignore Spelling: Poc + +using BenchmarkDotNet.Attributes; +using Collections.Benchmarks.Core; + +#pragma warning disable CA1822 // Mark members as static + +namespace Recyclable.Collections.Benchmarks.POC +{ + public class GreaterOperatorVsNotEqualOperatorBenchmarks + { + private static readonly long _num = RecyclableDefaults.MinItemsCountForParallelization; + + [GlobalSetup] + public void Setup() + { + Console.WriteLine($"*** We're comparing if {_num} is < 0 ***"); + } + + [Benchmark(Baseline = true)] + public void CompareWithGreater() + { + DoNothing.With(_num > 0 ? 1 : 0); + } + + [Benchmark] + public void CompareWithGreaterEqual() + { + DoNothing.With(_num >= 0 ? 1 : 0); + } + + [Benchmark] + public void CompareWithNotEqual() + { + DoNothing.With(_num != 0 ? 1 : 0); + } + + [Benchmark] + public void CompareWithLess() + { + DoNothing.With(_num < 0 ? 1 : 0); + } + + [Benchmark] + public void CompareWithEqual() + { + DoNothing.With(_num == 0 ? 0 : 1); + } + } +} diff --git a/Recyclable.Collections.Benchmarks/POC/GreaterOperatorvsDoesntEqualOperator.Benchmarks.cs b/Recyclable.Collections.Benchmarks/POC/GreaterOperatorvsDoesntEqualOperator.Benchmarks.cs deleted file mode 100644 index fbaac50..0000000 --- a/Recyclable.Collections.Benchmarks/POC/GreaterOperatorvsDoesntEqualOperator.Benchmarks.cs +++ /dev/null @@ -1,57 +0,0 @@ -using BenchmarkDotNet.Attributes; -using System.Runtime.CompilerServices; - -#pragma warning disable CA1822 - -namespace Recyclable.Collections.Benchmarks.POC -{ - public class GreaterOperatorVsDoesntEqualOperatorBenchmarks - { - private static readonly long num = RecyclableDefaults.MinItemsCountForParallelization; - - public void Setup() - { - Console.WriteLine($"*** We're comparing if {num} is < 0 ***"); - } - - public void Cleanup() { } - -#pragma warning disable RCS1163, IDE0060 - [MethodImpl(MethodImplOptions.NoInlining)] - private static void DoNothing(T item) - { - } - -#pragma warning restore RCS1163 - - [Benchmark(Baseline = true)] - public void CompareWithGreater() - { - DoNothing(num > 0 ? 1 : 0); - } - - [Benchmark] - public void CompareWithGreaterEqual() - { - DoNothing(num >= 0 ? 1 : 0); - } - - [Benchmark] - public void CompareWithDoesntEqual() - { - DoNothing(num != 0 ? 1 : 0); - } - - [Benchmark] - public void CompareWithLess() - { - DoNothing(num < 0 ? 1 : 0); - } - - [Benchmark] - public void CompareWithEqual() - { - DoNothing(num == 0 ? 0 : 1); - } - } -} diff --git a/Recyclable.Collections.Benchmarks/POC/LessOperatorvsAndOperatorBenchmarks.cs b/Recyclable.Collections.Benchmarks/POC/LessOperatorvsAndOperatorBenchmarks.cs index 2f89dcb..b0ad3d7 100644 --- a/Recyclable.Collections.Benchmarks/POC/LessOperatorvsAndOperatorBenchmarks.cs +++ b/Recyclable.Collections.Benchmarks/POC/LessOperatorvsAndOperatorBenchmarks.cs @@ -1,7 +1,7 @@ // Ignore Spelling: Poc using BenchmarkDotNet.Attributes; -using System.Runtime.CompilerServices; +using Collections.Benchmarks.Core; #pragma warning disable CA1822 @@ -21,36 +21,28 @@ namespace Recyclable.Collections.Benchmarks.POC public void Cleanup() { } -#pragma warning disable RCS1163, IDE0060 - [MethodImpl(MethodImplOptions.NoInlining)] - private static void DoNothing(T item) - { - } - -#pragma warning restore RCS1163 - [Benchmark(Baseline = true)] public void CompareWithLess() { - DoNothing(_num < 0); + DoNothing.With(_num < 0); } [Benchmark] public void CompareWithAnd() { - DoNothing((_num & BitShift) != 0); + DoNothing.With((_num & BitShift) != 0); } [Benchmark] public void CompareWithEqual() { - DoNothing(_num == -1); + DoNothing.With(_num == -1); } [Benchmark] public void CompareToZero() { - DoNothing(_num == 0); + DoNothing.With(_num == 0); } } } diff --git a/Recyclable.Collections.Benchmarks/POC/ModuloBenchmarks.cs b/Recyclable.Collections.Benchmarks/POC/ModuloBenchmarks.cs new file mode 100644 index 0000000..a2ee40e --- /dev/null +++ b/Recyclable.Collections.Benchmarks/POC/ModuloBenchmarks.cs @@ -0,0 +1,371 @@ +// Ignore Spelling: Mul Poc + +using BenchmarkDotNet.Attributes; +using Collections.Benchmarks.Core; +using System.Numerics; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; + +namespace Recyclable.Collections.Benchmarks.POC +{ + [MemoryDiagnoser] + public class ModuloBenchmarks + { + public static void Run() + { + var benchmark = new ModuloBenchmarks(); + benchmark.Setup(); + benchmark.AddWithFor(); + benchmark.AddWithForOptimized(); + benchmark.DividerAndModulusWithOperator(); + benchmark.MathDivRem(); + benchmark.MixedApproachWithForLoopOptimized(); + benchmark.MixedApproachWithSubtractWithStackalloc(); + benchmark.MixedApproachWithSubtractWithWhile(); + benchmark.MixedApproachWithSubtractWithWhileAsVector(); + benchmark.MixedApproachWithSubtractWithWhileWithSse2(); + benchmark.SubtractWithWhile(); + benchmark.SubtractWithWhileWithSse2(); + benchmark.XDivYMulX(); + benchmark.XDivYMulXWithLocalVar(); + } + + private long _cutoff; + private Vector128 _increment; + private long _lastCaseIndex; + + [GlobalSetup] + public void Setup() + { + _cutoff = checked((long)BlockSize << 4); + _increment = Vector128.Create(-BlockSize, 1L); + _lastCaseIndex = 0; + } + + //[Params(123, 10, 2, int.MaxValue, int.MaxValue / 2, int.MaxValue / 3, int.MaxValue / 4, int.MaxValue / 6, int.MaxValue / 10, int.MaxValue / 15, int.MaxValue / 20)] + [Params(int.MaxValue, int.MaxValue / 2, int.MaxValue / 3, int.MaxValue / 4, int.MaxValue / 6, int.MaxValue / 8, int.MaxValue / 10, int.MaxValue / 100)] + //[Params(int.MaxValue / 10, int.MaxValue / 20, int.MaxValue / 100)] + public int BlockSize { get; set; } = int.MaxValue; + + [Params(int.MaxValue, int.MaxValue / 1000, int.MaxValue / 10000)] + //[Params(int.MaxValue)] + //[Params(int.MaxValue * 100L)] + public long TestNumber { get; set; } = int.MaxValue; + + private void CalculateDividerAndModulusWithOperator(long i) + { + DoNothing.With(i / BlockSize, i % BlockSize); + } + + private void CalculateWithMathDivRem(long i) + { + DoNothing.With(Math.DivRem(i, BlockSize, out long remainder), remainder); + } + + private void CalculateWithAddWithFor(long i) + { + int result = 0; + int remainder = 0; + int blockSize = BlockSize; + for (long iteration = 0; iteration < i; iteration++) + { + if (remainder > blockSize - 1) + { + remainder = 0; + result++; + } + + remainder++; + } + + DoNothing.With(result, remainder); + } + + private void CalculateWithAddWithForOptimized(long i) + { + long total = 0; + int result = 0; + int blockSize = BlockSize; + while (total + blockSize <= i) + { + total += blockSize; + result++; + } + + DoNothing.With(result, i - total); + } + + private void CalculateWithXDivYMulX(long i) + { + DoNothing.With(i / BlockSize, i - (i / BlockSize * BlockSize)); + } + + private void CalculateWithXDivYMulXWithLocalVar(long i) + { + int blockSize = BlockSize; + int result = (int)(i / blockSize); + DoNothing.With(result, i - (result * blockSize)); + } + + private void CalculateWithSubtractWithWhile(long i) + { + int result = 0; + long remainder = i; + int blockSize = BlockSize; + while (remainder >= blockSize) + { + remainder -= blockSize; + result++; + } + + DoNothing.With(result, remainder); + } + + private void CalculateWithSubtractWithWhileWithSse2(long i) + { + var state = Vector128.Create(i, 0); + int blockSize = BlockSize; + var inc = _increment; + while (state.GetElement(0) >= blockSize) + { + state = Sse2.Add(state, inc); + } + + DoNothing.With(state.GetElement(1), state.GetElement(0)); + } + + private void CalculateWithMixedApproachWithSubtractWithWhile(long i) + { + long remainder; + if (i >= _cutoff) + { + DoNothing.With(Math.DivRem(i, BlockSize, out remainder), remainder); + } + else + { + int result = 0; + int blockSize = BlockSize; + remainder = i; + while (remainder >= blockSize) + { + remainder -= blockSize; + result++; + } + + DoNothing.With(result, remainder); + } + } + + private void CalculateWithMixedApproachWithSubtractWithWhileAsVector(long i) + { + if (i >= _cutoff) + { + DoNothing.With(Math.DivRem(i, BlockSize, out long remainder), remainder); + } + else + { + var state = new Vector(new[] { 0L, i, 0, 0 }); + var increment = new Vector(new[] { 1L, -BlockSize, 0, 0 }); + int blockSize = BlockSize; + while (state[1] >= blockSize) + { + state += increment; + } + + DoNothing.With(state[0], state[1]); + } + } + + private void CalculateWithMixedApproachWithSubtractWithWhileWithSse2(long i) + { + if (i >= _cutoff) + { + DoNothing.With(Math.DivRem(i, BlockSize, out long remainder), remainder); + } + else + { + var increment = _increment; + var state = Vector128.Create(i, 0); + int blockSize = BlockSize; + while (state.GetElement(0) >= blockSize) + { + state = Sse2.Add(state, increment); + } + + DoNothing.With(state.GetElement(1), state.GetElement(0)); + } + } + + private void CalculateWithMixedApproachWithSubtractWithStackalloc(long i) + { + if (i >= _cutoff) + { + DoNothing.With(Math.DivRem(i, BlockSize, out long remainder), remainder); + } + else + { + Span state = stackalloc long[2] { i, 0 };// Vector128.Create(BlockSize, 0); + int blockSize = BlockSize; + while (state[0] >= blockSize) + { + state[0] -= blockSize; + state[1]++; + } + + DoNothing.With(state[1], state[0]); + } + } + + private void CalculateWithMixedApproachWithForLoopOptimized(long i) + { + long total; + if (i >= _cutoff) + { + DoNothing.With(Math.DivRem(i, BlockSize, out total), total); + } + else + { + total = 0; + int result = 0; + int blockSize = BlockSize; + while (total + blockSize <= i) + { + total += blockSize; + result++; + } + + DoNothing.With(result, i - total); + } + } + + [Benchmark(Baseline = true)] + public void DividerAndModulusWithOperator() + { + long testNumber = TestNumber; + for (long i = testNumber; i >= _lastCaseIndex; i--) + { + CalculateDividerAndModulusWithOperator(i); + } + } + + [Benchmark] + public void MathDivRem() + { + long testNumber = TestNumber; + for (long i = testNumber; i >= _lastCaseIndex; i--) + { + CalculateWithMathDivRem(i); + } + } + + [Benchmark] + public void AddWithFor() + { + long testNumber = TestNumber; + for (long i = testNumber; i >= _lastCaseIndex; i--) + { + CalculateWithAddWithFor(i); + } + } + + [Benchmark(Baseline = true)] + public void AddWithForOptimized() + { + long testNumber = TestNumber; + for (long i = testNumber; i >= _lastCaseIndex; i--) + { + CalculateWithAddWithForOptimized(i); + } + } + + [Benchmark] + public void XDivYMulX() + { + long testNumber = TestNumber; + for (long i = testNumber; i >= _lastCaseIndex; i--) + { + CalculateWithXDivYMulX(i); + } + } + + [Benchmark] + public void XDivYMulXWithLocalVar() + { + long testNumber = TestNumber; + for (long i = testNumber; i >= _lastCaseIndex; i--) + { + CalculateWithXDivYMulXWithLocalVar(i); + } + } + + [Benchmark] + public void SubtractWithWhile() + { + long testNumber = TestNumber; + for (long i = testNumber; i >= _lastCaseIndex; i--) + { + CalculateWithSubtractWithWhile(i); + } + } + + [Benchmark] + public void SubtractWithWhileWithSse2() + { + long testNumber = TestNumber; + for (long i = testNumber; i >= _lastCaseIndex; i--) + { + CalculateWithSubtractWithWhileWithSse2(i); + } + } + + [Benchmark(Baseline = false)] + public void MixedApproachWithSubtractWithWhile() + { + long testNumber = TestNumber; + for (long i = testNumber; i >= _lastCaseIndex; i--) + { + CalculateWithMixedApproachWithSubtractWithWhile(i); + } + } + + [Benchmark(Baseline = false)] + public void MixedApproachWithSubtractWithWhileAsVector() + { + long testNumber = TestNumber; + for (long i = testNumber; i >= _lastCaseIndex; i--) + { + CalculateWithMixedApproachWithSubtractWithWhileAsVector(i); + } + } + + [Benchmark(Baseline = false)] + public void MixedApproachWithSubtractWithWhileWithSse2() + { + long testNumber = TestNumber; + for (long i = testNumber; i >= _lastCaseIndex; i--) + { + CalculateWithMixedApproachWithSubtractWithWhileWithSse2(i); + } + } + + [Benchmark(Baseline = false)] + public void MixedApproachWithSubtractWithStackalloc() + { + long testNumber = TestNumber; + for (long i = testNumber; i >= _lastCaseIndex; i--) + { + CalculateWithMixedApproachWithSubtractWithStackalloc(i); + } + } + + [Benchmark(Baseline = false)] + public void MixedApproachWithForLoopOptimized() + { + long testNumber = TestNumber; + for (long i = testNumber; i >= _lastCaseIndex; i--) + { + CalculateWithMixedApproachWithForLoopOptimized(i); + } + } + } +} \ No newline at end of file diff --git a/Recyclable.Collections.Benchmarks/POC/ModuloPoc.Benchmarks.cs b/Recyclable.Collections.Benchmarks/POC/ModuloPoc.Benchmarks.cs deleted file mode 100644 index 7416e5d..0000000 --- a/Recyclable.Collections.Benchmarks/POC/ModuloPoc.Benchmarks.cs +++ /dev/null @@ -1,376 +0,0 @@ -using BenchmarkDotNet.Attributes; -using System.Numerics; -using System.Runtime.CompilerServices; -using System.Runtime.Intrinsics; -using System.Runtime.Intrinsics.X86; - -#pragma warning disable xUnit1026, RCS1163, IDE0060 - -namespace Recyclable.Collections.Benchmarks.POC -{ - [MemoryDiagnoser] - public class ModuloPocBenchmarks - { - public static void Run() - { - var benchmark = new ModuloPocBenchmarks(); - benchmark.Setup(); - benchmark.AddWithFor(); - benchmark.AddWithForOptimized(); - benchmark.DividerAndModulusWithOperator(); - benchmark.MathDivRem(); - benchmark.MixedApproachWithForLoopOptimized(); - benchmark.MixedApproachWithSubtractWithStackalloc(); - benchmark.MixedApproachWithSubtractWithWhile(); - benchmark.MixedApproachWithSubtractWithWhileAsVector(); - benchmark.MixedApproachWithSubtractWithWhileWithSse2(); - benchmark.SubtractWithWhile(); - benchmark.SubtractWithWhileWithSse2(); - benchmark.XDivYMulX(); - benchmark.XDivYMulXWithLocalVar(); - } - - private long _cutoff; - private Vector128 _increment; - private long _lastCaseIndex; - - [GlobalSetup] - public void Setup() - { - _cutoff = checked((long)BlockSize << 4); - _increment = Vector128.Create(-BlockSize, 1L); - _lastCaseIndex = 0; - } - - private static void DoNothing(T result, T remainder, [CallerMemberName] string? callerName = null) - { - //Console.WriteLine($"{callerName}: result = {result}, remainder = {remainder}"); - } - - //[Params(123, 10, 2, int.MaxValue, int.MaxValue / 2, int.MaxValue / 3, int.MaxValue / 4, int.MaxValue / 6, int.MaxValue / 10, int.MaxValue / 15, int.MaxValue / 20)] - [Params(int.MaxValue, int.MaxValue / 2, int.MaxValue / 3, int.MaxValue / 4, int.MaxValue / 6, int.MaxValue / 8, int.MaxValue / 10, int.MaxValue / 100)] - //[Params(int.MaxValue / 10, int.MaxValue / 20, int.MaxValue / 100)] - public int BlockSize { get; set; } = int.MaxValue; - - [Params(int.MaxValue, int.MaxValue / 1000, int.MaxValue / 10000)] - //[Params(int.MaxValue)] - //[Params(int.MaxValue * 100L)] - public long TestNumber { get; set; } = int.MaxValue; - - private void CalculateDividerAndModulusWithOperator(long i) - { - DoNothing(i / BlockSize, i % BlockSize); - } - - private void CalculateWithMathDivRem(long i) - { - DoNothing(Math.DivRem(i, BlockSize, out long remainder), remainder); - } - - private void CalculateWithAddWithFor(long i) - { - int result = 0; - int remainder = 0; - int blockSize = BlockSize; - for (long iteration = 0; iteration < i; iteration++) - { - if (remainder > blockSize - 1) - { - remainder = 0; - result++; - } - - remainder++; - } - - DoNothing(result, remainder); - } - - private void CalculateWithAddWithForOptimized(long i) - { - long total = 0; - int result = 0; - int blockSize = BlockSize; - while (total + blockSize <= i) - { - total += blockSize; - result++; - } - - DoNothing(result, i - total); - } - - private void CalculateWithXDivYMulX(long i) - { - DoNothing(i / BlockSize, i - (i / BlockSize * BlockSize)); - } - - private void CalculateWithXDivYMulXWithLocalVar(long i) - { - int blockSize = BlockSize; - int result = (int)(i / blockSize); - DoNothing(result, i - (result * blockSize)); - } - - private void CalculateWithSubtractWithWhile(long i) - { - int result = 0; - long remainder = i; - int blockSize = BlockSize; - while (remainder >= blockSize) - { - remainder -= blockSize; - result++; - } - - DoNothing(result, remainder); - } - - private void CalculateWithSubtractWithWhileWithSse2(long i) - { - var state = Vector128.Create(i, 0); - int blockSize = BlockSize; - var inc = _increment; - while (state.GetElement(0) >= blockSize) - { - state = Sse2.Add(state, inc); - } - - DoNothing(state.GetElement(1), state.GetElement(0)); - } - - private void CalculateWithMixedApproachWithSubtractWithWhile(long i) - { - long remainder; - if (i >= _cutoff) - { - DoNothing(Math.DivRem(i, BlockSize, out remainder), remainder); - } - else - { - int result = 0; - int blockSize = BlockSize; - remainder = i; - while (remainder >= blockSize) - { - remainder -= blockSize; - result++; - } - - DoNothing(result, remainder); - } - } - - private void CalculateWithMixedApproachWithSubtractWithWhileAsVector(long i) - { - if (i >= _cutoff) - { - DoNothing(Math.DivRem(i, BlockSize, out long remainder), remainder); - } - else - { - var state = new Vector(new[] { 0L, i, 0, 0 }); - var increment = new Vector(new[] { 1L, -BlockSize, 0, 0 }); - int blockSize = BlockSize; - while (state[1] >= blockSize) - { - state += increment; - } - - DoNothing(state[0], state[1]); - } - } - - private void CalculateWithMixedApproachWithSubtractWithWhileWithSse2(long i) - { - if (i >= _cutoff) - { - DoNothing(Math.DivRem(i, BlockSize, out long remainder), remainder); - } - else - { - var increment = _increment; - var state = Vector128.Create(i, 0); - int blockSize = BlockSize; - while (state.GetElement(0) >= blockSize) - { - state = Sse2.Add(state, increment); - } - - DoNothing(state.GetElement(1), state.GetElement(0)); - } - } - - private void CalculateWithMixedApproachWithSubtractWithStackalloc(long i) - { - if (i >= _cutoff) - { - DoNothing(Math.DivRem(i, BlockSize, out long remainder), remainder); - } - else - { - Span state = stackalloc long[2] { i, 0 };// Vector128.Create(BlockSize, 0); - int blockSize = BlockSize; - while (state[0] >= blockSize) - { - state[0] -= blockSize; - state[1]++; - } - - DoNothing(state[1], state[0]); - } - } - - private void CalculateWithMixedApproachWithForLoopOptimized(long i) - { - long total; - if (i >= _cutoff) - { - DoNothing(Math.DivRem(i, BlockSize, out total), total); - } - else - { - total = 0; - int result = 0; - int blockSize = BlockSize; - while (total + blockSize <= i) - { - total += blockSize; - result++; - } - - DoNothing(result, i - total); - } - } - - [Benchmark(Baseline = true)] - public void DividerAndModulusWithOperator() - { - long testNumber = TestNumber; - for (long i = testNumber; i >= _lastCaseIndex; i--) - { - CalculateDividerAndModulusWithOperator(i); - } - } - - [Benchmark] - public void MathDivRem() - { - long testNumber = TestNumber; - for (long i = testNumber; i >= _lastCaseIndex; i--) - { - CalculateWithMathDivRem(i); - } - } - - [Benchmark] - public void AddWithFor() - { - long testNumber = TestNumber; - for (long i = testNumber; i >= _lastCaseIndex; i--) - { - CalculateWithAddWithFor(i); - } - } - - [Benchmark(Baseline = true)] - public void AddWithForOptimized() - { - long testNumber = TestNumber; - for (long i = testNumber; i >= _lastCaseIndex; i--) - { - CalculateWithAddWithForOptimized(i); - } - } - - [Benchmark] - public void XDivYMulX() - { - long testNumber = TestNumber; - for (long i = testNumber; i >= _lastCaseIndex; i--) - { - CalculateWithXDivYMulX(i); - } - } - - [Benchmark] - public void XDivYMulXWithLocalVar() - { - long testNumber = TestNumber; - for (long i = testNumber; i >= _lastCaseIndex; i--) - { - CalculateWithXDivYMulXWithLocalVar(i); - } - } - - [Benchmark] - public void SubtractWithWhile() - { - long testNumber = TestNumber; - for (long i = testNumber; i >= _lastCaseIndex; i--) - { - CalculateWithSubtractWithWhile(i); - } - } - - [Benchmark] - public void SubtractWithWhileWithSse2() - { - long testNumber = TestNumber; - for (long i = testNumber; i >= _lastCaseIndex; i--) - { - CalculateWithSubtractWithWhileWithSse2(i); - } - } - - [Benchmark(Baseline = false)] - public void MixedApproachWithSubtractWithWhile() - { - long testNumber = TestNumber; - for (long i = testNumber; i >= _lastCaseIndex; i--) - { - CalculateWithMixedApproachWithSubtractWithWhile(i); - } - } - - [Benchmark(Baseline = false)] - public void MixedApproachWithSubtractWithWhileAsVector() - { - long testNumber = TestNumber; - for (long i = testNumber; i >= _lastCaseIndex; i--) - { - CalculateWithMixedApproachWithSubtractWithWhileAsVector(i); - } - } - - [Benchmark(Baseline = false)] - public void MixedApproachWithSubtractWithWhileWithSse2() - { - long testNumber = TestNumber; - for (long i = testNumber; i >= _lastCaseIndex; i--) - { - CalculateWithMixedApproachWithSubtractWithWhileWithSse2(i); - } - } - - [Benchmark(Baseline = false)] - public void MixedApproachWithSubtractWithStackalloc() - { - long testNumber = TestNumber; - for (long i = testNumber; i >= _lastCaseIndex; i--) - { - CalculateWithMixedApproachWithSubtractWithStackalloc(i); - } - } - - [Benchmark(Baseline = false)] - public void MixedApproachWithForLoopOptimized() - { - long testNumber = TestNumber; - for (long i = testNumber; i >= _lastCaseIndex; i--) - { - CalculateWithMixedApproachWithForLoopOptimized(i); - } - } - } -} \ No newline at end of file diff --git a/Recyclable.Collections.Benchmarks/POC/PocBenchmarkBase.cs b/Recyclable.Collections.Benchmarks/POC/PocBenchmarkBase.cs deleted file mode 100644 index 368112a..0000000 --- a/Recyclable.Collections.Benchmarks/POC/PocBenchmarkBase.cs +++ /dev/null @@ -1,142 +0,0 @@ -using BenchmarkDotNet.Attributes; -using System.Numerics; -using System.Runtime.CompilerServices; - -namespace Recyclable.Collections.Benchmarks.POC -{ - public abstract class PocBenchmarkBase - { - public virtual TBenchmarkType? DataType { get; set; } - public virtual TBenchmarkType? BaseDataType { get; set; } - - private Action? _testMethod; - protected Action TestMethod - { - get => _testMethod ?? throw new OperationCanceledException("Skip - No actual defined"); - set => _testMethod = value; - } - - private Action? _baselineMethod; - protected Action BaselineMethod - { - get => _baselineMethod ?? throw new OperationCanceledException("Skip - No baseline defined"); - set => _baselineMethod = value; - } - - [Benchmark(Baseline = true)] - public void Baseline() => BaselineMethod.Invoke(); - - [Benchmark] - public void Actual() => TestMethod.Invoke(); - - // 0 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 32768 65536 131072 262144 524_288 - // 1048576 2097152 4194304 8388608 16777216 33554432 67108864 134217728 268435456 536870912 - // 1073741824 2147483648 - - // [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 32, 40, 50, 60, 80, 90, 100, 128, 256, 512, 1024, 2048, 4096, 8192, 1_000_000)] - // [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 32, 40, 50, 60, 80, 90, 100, 128, 256, 512, 1024, 2048, 4096, 8192, 1_000_000)] - // [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 32, 40, 50, 60, 80, 90, 100, 128, 256, 512, 1024, 2048, 4096, 8192, 100_000_000)] - // [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 32, 40, 50, 60, 80, 90, 100, 128, 256, 512, 1024, 2048, 4096, 8192, 850_000 - 1, 1_000_000, RecyclableDefaults.MaxPooledBlockSize)] - // [Params(1_000_000, 10_000_000, 100_000_000, 1_000_000_000)] - // [Params(1, 10, 64, 128, 192, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144)] - // [Params(524_288, 786_432, 1_048_576)] - // [Params(262_144, 393_216, 524_288)] - // [Params(850_000_000)] - // [Params(100_000_000)] - // [Params(RecyclableDefaults.MinItemsCountForParallelization)] - // [Params(127)] - // [Params(16)] - // [Params(10, 15, 128)] - // [Params(1)] - // [Params(RecyclableDefaults.MaxPooledBlockSize)] - // [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 32, 40, 50, 60, 80, 90, 100, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 10_000_000, 33_554_432, 50_000_000, 100_000_000)] - // *** [Params(RecyclableDefaults.MinPooledArrayLength - 3, RecyclableDefaults.MinPooledArrayLength - 2, RecyclableDefaults.MinPooledArrayLength - 1, RecyclableDefaults.MinPooledArrayLength, RecyclableDefaults.MinPooledArrayLength + 1, RecyclableDefaults.MinPooledArrayLength + 2, RecyclableDefaults.MinPooledArrayLength + 3)] - [Params(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 32, 40, RecyclableDefaults.MinPooledArrayLength - 1, RecyclableDefaults.MinPooledArrayLength, 40, 50, 60, 70, 80, 90, 100, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, RecyclableDefaults.MinItemsCountForParallelization)] - // *** [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 32, 40, RecyclableDefaults.MinPooledArrayLength - 1, RecyclableDefaults.MinPooledArrayLength, 40, 50, 60, 70, 80, 90, 100, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, RecyclableDefaults.MinItemsCountForParallelization)] - // [Params(256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, RecyclableDefaults.MinItemsCountForParallelization)] - // [Params(RecyclableDefaults.MinItemsCountForParallelization, 1_048_576, 2_097_152, 4_194_304, 8_388_608, 16_777_216, 33_554_432, RecyclableDefaults.MaxPooledBlockSize)] - // *** [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, RecyclableDefaults.MinPooledArrayLength - 1, RecyclableDefaults.MinPooledArrayLength, 40, 50, 60, 64, 70, 80, 90, 100, 127, 128)] - // [Params(1, 10, 1024, 10240, RecyclableDefaults.MinPooledArrayLength, RecyclableDefaults.MinItemsCountForParallelization)] - // [Params(RecyclableDefaults.MinItemsCountForParallelization * 3)] - // [Params(1_048_576)] - public virtual int TestObjectCount { get; set; } = 0; //8_192;//131_072; //1; //33_554_432; //524_288; //131_072; - public virtual int TestObjectCountForSlowMethods { get; private set; } - - // [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200)] - // [Params(10, 20, 50, 100)] - // [Params(1, 10)] - public int Divider = 10; - //public int BlockSize = 1_048_576;//int.MaxValue - 1; - public int BlockSize { get; private set; } - - public byte BlockSizePow2BitShift => checked((byte)(31 - BitOperations.LeadingZeroCount((uint)BlockSize))); - - [MethodImpl(MethodImplOptions.NoInlining)] - protected static void DoNothing(in T item) - { - _ = item; - } - - protected static Exception CreateUnknownBenchmarkTypeException(T benchmarkType) - { - return new InvalidOperationException($"******* UNKNOWN BENCHMARK TYPE {{{benchmarkType}}} *******"); - } - - protected static Exception CreateMethodNotFoundException(in string methodName, in string? className) - { - return new MethodAccessException($"******* METHOD {{{methodName}}} NOT FOUND IN CLASS {{{className}}} *******"); - } - - protected virtual void PrepareData(T benchmarkType) { } - protected virtual Action? GetTestMethod(TBenchmarkType? benchmarkType) => null; - - [GlobalCleanup] - public virtual void Cleanup() - { - _baselineMethod = null; - _testMethod = null; - GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true); - } - - [GlobalSetup] - public virtual void Setup() - { - Console.WriteLine($"******* SETTING UP TEST CASE FOR BENCHMARK {{{DataType}}} *******"); - - TestObjectCountForSlowMethods = (TestObjectCount / 2) + 1; - - BlockSize = TestObjectCount switch - { - 0 => 1, - > 0 and <= 10_240 => TestObjectCount, - _ => TestObjectCount / Divider > 0 ? TestObjectCount / Divider : TestObjectCount - }; - - if (BlockSize > 0) - { - BlockSize = checked((int)BitOperations.RoundUpToPowerOf2((uint)BlockSize)); - } - - Console.WriteLine($"******* BaseDataType = {BaseDataType}; default = {default(TBenchmarkType)} *******"); - - if (!EqualityComparer.Default.Equals(BaseDataType, default)) - { - Console.WriteLine("******* SETTING UP BASELINE DATA *******"); - PrepareData(BaseDataType); - _baselineMethod = GetTestMethod(BaseDataType); - } - - //~ We don't want to prepare data if baseline data is the same is benchmark data. - //~ One would override another - waste of time & resources. - if (!EqualityComparer.Default.Equals(BaseDataType, DataType)) - { - Console.WriteLine("******* SETTING UP TEST CASE DATA *******"); - //~ If BaseDataType == null, then we'll come here only if DataType != null. - PrepareData(DataType!); - _testMethod = GetTestMethod(DataType); - } - - Console.WriteLine("******* DATA PREPARED *******"); - } - } -} diff --git a/Recyclable.Collections.Benchmarks/POC/RecyclableLongListPos.Benchmarks.IndexOf.txt b/Recyclable.Collections.Benchmarks/POC/RecyclableLongListBenchmarks.IndexOf.txt similarity index 100% rename from Recyclable.Collections.Benchmarks/POC/RecyclableLongListPos.Benchmarks.IndexOf.txt rename to Recyclable.Collections.Benchmarks/POC/RecyclableLongListBenchmarks.IndexOf.txt diff --git a/Recyclable.Collections.Benchmarks/RecyclableBenchmarkBase.cs b/Recyclable.Collections.Benchmarks/POC/RecyclableLongListBenchmarks.cs similarity index 53% rename from Recyclable.Collections.Benchmarks/RecyclableBenchmarkBase.cs rename to Recyclable.Collections.Benchmarks/POC/RecyclableLongListBenchmarks.cs index 3dbfcd2..5ef2929 100644 --- a/Recyclable.Collections.Benchmarks/RecyclableBenchmarkBase.cs +++ b/Recyclable.Collections.Benchmarks/POC/RecyclableLongListBenchmarks.cs @@ -1,104 +1,48 @@ -using BenchmarkDotNet.Attributes; +// Ignore Spelling: POC + +using System.Reflection; +using BenchmarkDotNet.Attributes; using Collections.Pooled; -using Recyclable.Collections.Benchmarks.Core; -using Recyclable.Collections.Benchmarks.POC; +using Collections.Benchmarks.Core; -namespace Recyclable.Collections.Benchmarks +namespace Recyclable.Collections.Benchmarks.POC { - public enum RecyclableCollectionsBenchmarkSource - { - Unknown, - Array, - List, - PooledList, - RecyclableList, - RecyclableLongList, - } - [MemoryDiagnoser] - public class RecyclableBenchmarkBase : PocBenchmarkBase + public partial class RecyclableLongListBenchmarks : BaselineVsActualBenchmarkBase { - protected long[]? _testObjects; - protected long[] TestObjects => _testObjects ?? throw new NullReferenceException("Something is wrong and the field is not initialized"); + private int[]? _testArray; + public int[] TestObjects => _testArray ?? throw new NullReferenceException("Something is wrong and test objects are null"); - protected List? _testObjectsAsList; - protected List TestObjectsAsList => _testObjectsAsList ?? throw new NullReferenceException("Something went wrong and the field is not initialized"); + public RecyclableLongList TestObjectsAsRecyclableLongList => _testRecyclableLongList ?? throw new NullReferenceException($"Something is wrong and {nameof(RecyclableLongList)} is null"); + private RecyclableLongList? _testRecyclableLongList; + private PooledList? _testPooledList; + internal PooledList TestPooledList => _testPooledList ?? throw new NullReferenceException($"Something is wrong and {nameof(PooledList)} is null"); - protected PooledList? _testObjectsAsPooledList; - public PooledList TestObjectsAsPooledList => _testObjectsAsPooledList ?? throw new NullReferenceException("Something is wrong and the field is not initialized"); - protected RecyclableList? _testObjectsAsRecyclableList; - protected RecyclableList TestObjectsAsRecyclableList => _testObjectsAsRecyclableList ?? throw new NullReferenceException("Something is wrong and the field is not initialized"); - protected RecyclableLongList? _testObjectsAsRecyclableLongList; - protected RecyclableLongList TestObjectsAsRecyclableLongList => _testObjectsAsRecyclableLongList ?? throw new NullReferenceException("Something is wrong and the field is not initialized"); - protected IEnumerable TestObjectsAsIEnumerable + private static readonly MethodInfo _ensureCapacityNewFunc; + + static RecyclableLongListBenchmarks() { - get - { - for (long i = 0; i < TestObjectCount; i++) - { - yield return i; - } - } + _ensureCapacityNewFunc = typeof(RecyclableLongList).GetMethod("EnsureCapacity", BindingFlags.Static | BindingFlags.NonPublic) + ?? throw new NullReferenceException($"Method EnsureCapacity not found in class {nameof(RecyclableLongList)}"); + } public override void Setup() { - PrepareData(RecyclableCollectionsBenchmarkSource.Array); + Console.WriteLine("******* SETTING UP EXPECTED RESULTS DATA *******"); + _testArray = DataGenerator.EnumerateTestObjects(TestObjectCount); + base.Setup(); } - protected override void PrepareData(T benchmarkType) - { - Console.WriteLine($"******* PREPARING DATA FOR {benchmarkType} *******"); - switch (benchmarkType) - { - case RecyclableCollectionsBenchmarkSource.Unknown: - break; - - case RecyclableCollectionsBenchmarkSource.Array: - _testObjects ??= DataGenerator.EnumerateTestObjects(TestObjectCount); - break; - - case RecyclableCollectionsBenchmarkSource.List: - _testObjectsAsList ??= TestObjects.ToList(); - break; - - case RecyclableCollectionsBenchmarkSource.PooledList: - _testObjectsAsPooledList ??= new PooledList(TestObjects, ClearMode.Auto); - break; - - case RecyclableCollectionsBenchmarkSource.RecyclableList: - _testObjectsAsRecyclableList ??= new(TestObjects, initialCapacity: TestObjectCount); - break; - - case RecyclableCollectionsBenchmarkSource.RecyclableLongList: - _testObjectsAsRecyclableLongList ??= new(TestObjects, BlockSize, initialCapacity: base.TestObjectCount); - break; - - default: - throw CreateUnknownBenchmarkTypeException(benchmarkType); - } - - base.PrepareData(benchmarkType); - } - public override void Cleanup() { - Console.WriteLine("******* GLOBAL CLEANUP *******"); - // Enable this if item type is changed to reference type - //if (_testObjects != null) - //{ - // Array.Fill(_testObjects, 0); - //} + _testArray = null; + _testRecyclableLongList?.Dispose(); + _testRecyclableLongList = null; + _testPooledList?.Dispose(); + _testPooledList = null; - _testObjects = default; - _testObjectsAsList = default; - _testObjectsAsPooledList?.Dispose(); - _testObjectsAsPooledList = default; - _testObjectsAsRecyclableList?.Dispose(); - _testObjectsAsRecyclableList = default; - _testObjectsAsRecyclableLongList?.Dispose(); - _testObjectsAsRecyclableLongList = default; base.Cleanup(); } } @@ -112,12 +56,12 @@ namespace Recyclable.Collections.Benchmarks // var data = TestObjects; // var dataCount = TestObjectCount; // using var list = new RecyclableList(initialCapacity: dataCount); - // for (long i = 0; i < dataCount; i++) + // for (int i = 0; i < dataCount; i++) // { // list.Add(data[i]); // } - // for (long i = 0; i < list.LongCount; i++) + // for (int i = 0; i < list.LongCount; i++) // { // DoNothing(list[i]); // } @@ -129,14 +73,14 @@ namespace Recyclable.Collections.Benchmarks // public void RecyclableLongList() // { // var data = TestObjects; - // long dataCount = TestObjectCount; + // int dataCount = TestObjectCount; // using var list = new RecyclableLongList(BlockSize, totalItemsCount: dataCount); - // for (long i = 0; i < dataCount; i++) + // for (int i = 0; i < dataCount; i++) // { // list.Add(data[i]); // } - // for (long i = 0; i < list.LongCount; i++) + // for (int i = 0; i < list.LongCount; i++) // { // DoNothing(list[i]); // } @@ -225,7 +169,7 @@ namespace Recyclable.Collections.Benchmarks // { // var data = TestObjects; // var dataCount = TestObjectCount; - // var list = new PriorityQueue(initialCapacity: dataCount); + // var list = new PriorityQueue(initialCapacity: dataCount); // for (var i = 0; i < dataCount; i++) // { // list.Enqueue(data[i], i); @@ -244,7 +188,7 @@ namespace Recyclable.Collections.Benchmarks // { // var data = TestObjects; // var dataCount = TestObjectCount; - // var list = new RecyclableSortedList(BlockSize); + // var list = new RecyclableSortedList(BlockSize); // list.BeginUpdate(); // for (var i = 0; i < dataCount; i++) // { @@ -266,7 +210,7 @@ namespace Recyclable.Collections.Benchmarks // { // var data = TestObjects; // var dataCount = TestObjectCount; - // var list = new RecyclableSortedList(BlockSize); + // var list = new RecyclableSortedList(BlockSize); // for (var i = 0; i < dataCount; i++) // { // list.Add(i, data[i]); @@ -285,7 +229,7 @@ namespace Recyclable.Collections.Benchmarks // { // var data = TestObjects; // var dataCount = TestObjectCount; - // var list = new SortedList(); + // var list = new SortedList(); // for (var i = 0; i < dataCount; i++) // { // list.Add(i, data[i]); diff --git a/Recyclable.Collections.Benchmarks/POC/RecyclableLongListPoc.Benchmarks.cs b/Recyclable.Collections.Benchmarks/POC/RecyclableLongListPoc.Benchmarks.cs deleted file mode 100644 index b9dfec1..0000000 --- a/Recyclable.Collections.Benchmarks/POC/RecyclableLongListPoc.Benchmarks.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System.Reflection; -using BenchmarkDotNet.Attributes; -using Collections.Pooled; -using Recyclable.Collections.Benchmarks.Core; - -namespace Recyclable.Collections.Benchmarks.POC -{ - [MemoryDiagnoser] - public partial class RecyclableLongListPocBenchmarks : PocBenchmarkBase - { - private long[]? _testArray; - public long[] TestObjects => _testArray ?? throw new NullReferenceException("Something is wrong and test objects are null"); - - public RecyclableLongList TestObjectsAsRecyclableLongList => _testRecyclableLongList ?? throw new NullReferenceException($"Something is wrong and {nameof(RecyclableLongList)} is null"); - private RecyclableLongList? _testRecyclableLongList; - private PooledList? _testPooledList; - internal PooledList TestPooledList => _testPooledList ?? throw new NullReferenceException($"Something is wrong and {nameof(PooledList)} is null"); - - private static readonly MethodInfo _ensureCapacityNewFunc; - - static RecyclableLongListPocBenchmarks() - { - _ensureCapacityNewFunc = typeof(RecyclableLongList).GetMethod("EnsureCapacity", BindingFlags.Static | BindingFlags.NonPublic) - ?? throw new NullReferenceException($"Method EnsureCapacity not found in class {nameof(RecyclableLongList)}"); - - } - - public override void Setup() - { - Console.WriteLine("******* SETTING UP EXPECTED RESULTS DATA *******"); - _testArray = DataGenerator.EnumerateTestObjects(TestObjectCount); - - base.Setup(); - } - - public override void Cleanup() - { - _testArray = null; - _testRecyclableLongList?.Dispose(); - _testRecyclableLongList = null; - _testPooledList?.Dispose(); - _testPooledList = null; - - base.Cleanup(); - } - } -} diff --git a/Recyclable.Collections.Benchmarks/POC/RefVsInstanceMemberBenchmarks.cs b/Recyclable.Collections.Benchmarks/POC/RefVsInstanceMemberBenchmarks.cs new file mode 100644 index 0000000..fd3ca00 --- /dev/null +++ b/Recyclable.Collections.Benchmarks/POC/RefVsInstanceMemberBenchmarks.cs @@ -0,0 +1,360 @@ +// Ignore Spelling: Poc + +using BenchmarkDotNet.Attributes; +using Collections.Benchmarks.Core; + +namespace Recyclable.Collections.Benchmarks.POC +{ + public class RefVsInstanceMemberBenchmarks + { + public static void Run() + { + var benchmark = new RefVsInstanceMemberBenchmarks(); + benchmark.ArrayInstanceMember2(); + benchmark.ArrayInstanceMember3(); + benchmark.ArrayInstanceMember4(); + benchmark.ArrayInstanceMember5(); + benchmark.ArrayInstanceMember6(); + benchmark.ArrayInstanceMemberLocalVar5(); + benchmark.ArrayInstanceMemberLocalVar6(); + benchmark.IntInstanceMember2(); + benchmark.IntInstanceMember3(); + benchmark.IntInstanceMember4(); + benchmark.IntInstanceMember5(); + benchmark.RefToArray2(); + benchmark.RefToArray3(); + benchmark.RefToArray4(); + benchmark.RefToArray5(); + benchmark.RefToArray6(); + benchmark.RefToInt2(); + benchmark.RefToInt3(); + } + + private readonly TestCase _testCase = new(); + private class TestCase + { + private int[] _items = new int[123]; + private int _count = 123; + private static int Add(int count) + { + return count; + } + + public int Count + { + get => _count; + set => _count = value; + } + + public ref int GetCountAsRefCount2() + { + ref int count = ref _count; + count = 234; + return ref count; + } + + public ref int GetCountAsRefCount3() + { + ref int count = ref _count; + count = 234; + _ = TestCase.Add(count); + return ref count; + } + + public ref int GetCountAsRefCount4() + { + ref int count = ref _count; + count = 234; + _ = TestCase.Add(count); + _ = TestCase.Add(count); + return ref count; + } + + public ref int GetCountAsRefCount5() + { + ref int count = ref _count; + count = 234; + _ = TestCase.Add(count); + _ = TestCase.Add(count); + _ = TestCase.Add(count); + return ref count; + } + + public int GetCountAsInstanceMember2() + { + _count = 234; + return _count; + } + + public int GetCountAsInstanceMember3() + { + _count = 234; + _ = TestCase.Add(_count); + return _count; + } + + public int GetCountAsInstanceMember4() + { + _count = 234; + _ = TestCase.Add(_count); + _ = TestCase.Add(_count); + return _count; + } + + public int GetCountAsInstanceMember5() + { + _count = 234; + _ = TestCase.Add(_count); + _ = TestCase.Add(_count); + _ = TestCase.Add(_count); + return _count; + } + + public int GetLengthAsArray2() + { + _ = TestCase.Add(_items.Length); + return _items.Length; + } + + public int GetLengthAsArray3() + { + _ = TestCase.Add(_items.Length); + _ = TestCase.Add(_items.Length); + return _items.Length; + } + + public int GetLengthAsArray4() + { + _ = TestCase.Add(_items.Length); + _ = TestCase.Add(_items.Length); + _ = TestCase.Add(_items.Length); + return _items.Length; + } + + public int GetLengthAsArray5() + { + _ = TestCase.Add(_items.Length); + _ = TestCase.Add(_items.Length); + _ = TestCase.Add(_items.Length); + _ = TestCase.Add(_items.Length); + return _items.Length; + } + + public int GetLengthAsArray6() + { + _ = TestCase.Add(_items.Length); + _ = TestCase.Add(_items.Length); + _ = TestCase.Add(_items.Length); + _ = TestCase.Add(_items.Length); + _ = TestCase.Add(_items.Length); + return _items.Length; + } + + public int GetLengthAsArrayLocalVar5() + { + var items = _items; + _ = TestCase.Add(items.Length); + _ = TestCase.Add(items.Length); + _ = TestCase.Add(items.Length); + _ = TestCase.Add(items.Length); + return items.Length; + } + + public int GetLengthAsArrayLocalVar6() + { + var items = _items; + _ = TestCase.Add(items.Length); + _ = TestCase.Add(items.Length); + _ = TestCase.Add(items.Length); + _ = TestCase.Add(items.Length); + _ = TestCase.Add(items.Length); + return items.Length; + } + + public int GetLengthAsRefArray2() + { + ref int[] items = ref _items; + _ = TestCase.Add(items.Length); + return items.Length; + } + + public int GetLengthAsRefArray3() + { + ref int[] items = ref _items; + _ = TestCase.Add(items.Length); + _ = TestCase.Add(items.Length); + return items.Length; + } + + public int GetLengthAsRefArray4() + { + ref int[] items = ref _items; + _ = TestCase.Add(items.Length); + _ = TestCase.Add(items.Length); + _ = TestCase.Add(items.Length); + return items.Length; + } + + public int GetLengthAsRefArray5() + { + ref int[] items = ref _items; + _ = TestCase.Add(items.Length); + _ = TestCase.Add(items.Length); + _ = TestCase.Add(items.Length); + _ = TestCase.Add(items.Length); + return items.Length; + } + + public int GetLengthAsRefArray6() + { + ref int[] items = ref _items; + _ = TestCase.Add(items.Length); + _ = TestCase.Add(items.Length); + _ = TestCase.Add(items.Length); + _ = TestCase.Add(items.Length); + _ = TestCase.Add(items.Length); + return items.Length; + } + } + + [Benchmark] + public void RefToInt2() + { + var count = _testCase.GetCountAsRefCount2(); + DoNothing.With(count); + } + + [Benchmark] + public void RefToInt3() + { + var count = _testCase.GetCountAsRefCount3(); + DoNothing.With(count); + } + + [Benchmark] + public void RefToInt4() + { + var count = _testCase.GetCountAsRefCount4(); + DoNothing.With(count); + } + + [Benchmark] + public void RefToInt5() + { + var count = _testCase.GetCountAsRefCount5(); + DoNothing.With(count); + } + + [Benchmark(Baseline = true)] + public void IntInstanceMember2() + { + var count = _testCase.GetCountAsInstanceMember2(); + DoNothing.With(count); + } + + [Benchmark(Baseline = false)] + public void IntInstanceMember3() + { + var count = _testCase.GetCountAsInstanceMember3(); + DoNothing.With(count); + } + + [Benchmark(Baseline = false)] + public void IntInstanceMember4() + { + var count = _testCase.GetCountAsInstanceMember4(); + DoNothing.With(count); + } + + [Benchmark(Baseline = false)] + public void IntInstanceMember5() + { + var count = _testCase.GetCountAsInstanceMember5(); + DoNothing.With(count); + } + + [Benchmark] + public void RefToArray2() + { + var count = _testCase.GetLengthAsRefArray2(); + DoNothing.With(count); + } + + [Benchmark] + public void RefToArray3() + { + var count = _testCase.GetLengthAsRefArray3(); + DoNothing.With(count); + } + + [Benchmark] + public void RefToArray4() + { + var count = _testCase.GetLengthAsRefArray4(); + DoNothing.With(count); + } + + [Benchmark] + public void RefToArray5() + { + var count = _testCase.GetLengthAsRefArray5(); + DoNothing.With(count); + } + + [Benchmark] + public void RefToArray6() + { + var count = _testCase.GetLengthAsRefArray6(); + DoNothing.With(count); + } + + [Benchmark(Baseline = false)] + public void ArrayInstanceMember2() + { + var count = _testCase.GetLengthAsArray2(); + DoNothing.With(count); + } + + [Benchmark(Baseline = false)] + public void ArrayInstanceMember3() + { + var count = _testCase.GetLengthAsArray3(); + DoNothing.With(count); + } + + [Benchmark(Baseline = false)] + public void ArrayInstanceMember4() + { + var count = _testCase.GetLengthAsArray4(); + DoNothing.With(count); + } + + [Benchmark(Baseline = false)] + public void ArrayInstanceMember5() + { + var count = _testCase.GetLengthAsArray5(); + DoNothing.With(count); + } + + [Benchmark(Baseline = false)] + public void ArrayInstanceMember6() + { + var count = _testCase.GetLengthAsArray6(); + DoNothing.With(count); + } + + [Benchmark(Baseline = false)] + public void ArrayInstanceMemberLocalVar5() + { + var count = _testCase.GetLengthAsArrayLocalVar5(); + DoNothing.With(count); + } + + [Benchmark(Baseline = false)] + public void ArrayInstanceMemberLocalVar6() + { + var count = _testCase.GetLengthAsArrayLocalVar6(); + DoNothing.With(count); + } + } +} diff --git a/Recyclable.Collections.Benchmarks/POC/RefVsInstanceMemberPoc.Benchmarks.cs b/Recyclable.Collections.Benchmarks/POC/RefVsInstanceMemberPoc.Benchmarks.cs deleted file mode 100644 index 4219f49..0000000 --- a/Recyclable.Collections.Benchmarks/POC/RefVsInstanceMemberPoc.Benchmarks.cs +++ /dev/null @@ -1,364 +0,0 @@ -using BenchmarkDotNet.Attributes; - -#pragma warning disable RCS1085 - -namespace Recyclable.Collections.Benchmarks.POC -{ - public class RefVsInstanceMemberPocBenchmarks - { - public static void Run() - { - var benchmark = new RefVsInstanceMemberPocBenchmarks(); - benchmark.ArrayInstanceMember2(); - benchmark.ArrayInstanceMember3(); - benchmark.ArrayInstanceMember4(); - benchmark.ArrayInstanceMember5(); - benchmark.ArrayInstanceMember6(); - benchmark.ArrayInstanceMemberLocalVar5(); - benchmark.ArrayInstanceMemberLocalVar6(); - benchmark.IntInstanceMember2(); - benchmark.IntInstanceMember3(); - benchmark.IntInstanceMember4(); - benchmark.IntInstanceMember5(); - benchmark.RefToArray2(); - benchmark.RefToArray3(); - benchmark.RefToArray4(); - benchmark.RefToArray5(); - benchmark.RefToArray6(); - benchmark.RefToInt2(); - benchmark.RefToInt3(); - } - - private readonly TestCase _testCase = new(); - private static void DoNothing(int count) - { - _ = count; - } - - private class TestCase - { - private int[] _items = new int[123]; - private int _count = 123; - private static int Add(int count) - { - return count; - } - - public int Count - { - get => _count; - set => _count = value; - } - - public ref int GetCountAsRefCount2() - { - ref int count = ref _count; - count = 234; - return ref count; - } - - public ref int GetCountAsRefCount3() - { - ref int count = ref _count; - count = 234; - _ = TestCase.Add(count); - return ref count; - } - - public ref int GetCountAsRefCount4() - { - ref int count = ref _count; - count = 234; - _ = TestCase.Add(count); - _ = TestCase.Add(count); - return ref count; - } - - public ref int GetCountAsRefCount5() - { - ref int count = ref _count; - count = 234; - _ = TestCase.Add(count); - _ = TestCase.Add(count); - _ = TestCase.Add(count); - return ref count; - } - - public int GetCountAsInstanceMember2() - { - _count = 234; - return _count; - } - - public int GetCountAsInstanceMember3() - { - _count = 234; - _ = TestCase.Add(_count); - return _count; - } - - public int GetCountAsInstanceMember4() - { - _count = 234; - _ = TestCase.Add(_count); - _ = TestCase.Add(_count); - return _count; - } - - public int GetCountAsInstanceMember5() - { - _count = 234; - _ = TestCase.Add(_count); - _ = TestCase.Add(_count); - _ = TestCase.Add(_count); - return _count; - } - - public int GetLengthAsArray2() - { - _ = TestCase.Add(_items.Length); - return _items.Length; - } - - public int GetLengthAsArray3() - { - _ = TestCase.Add(_items.Length); - _ = TestCase.Add(_items.Length); - return _items.Length; - } - - public int GetLengthAsArray4() - { - _ = TestCase.Add(_items.Length); - _ = TestCase.Add(_items.Length); - _ = TestCase.Add(_items.Length); - return _items.Length; - } - - public int GetLengthAsArray5() - { - _ = TestCase.Add(_items.Length); - _ = TestCase.Add(_items.Length); - _ = TestCase.Add(_items.Length); - _ = TestCase.Add(_items.Length); - return _items.Length; - } - - public int GetLengthAsArray6() - { - _ = TestCase.Add(_items.Length); - _ = TestCase.Add(_items.Length); - _ = TestCase.Add(_items.Length); - _ = TestCase.Add(_items.Length); - _ = TestCase.Add(_items.Length); - return _items.Length; - } - - public int GetLengthAsArrayLocalVar5() - { - var items = _items; - _ = TestCase.Add(items.Length); - _ = TestCase.Add(items.Length); - _ = TestCase.Add(items.Length); - _ = TestCase.Add(items.Length); - return items.Length; - } - - public int GetLengthAsArrayLocalVar6() - { - var items = _items; - _ = TestCase.Add(items.Length); - _ = TestCase.Add(items.Length); - _ = TestCase.Add(items.Length); - _ = TestCase.Add(items.Length); - _ = TestCase.Add(items.Length); - return items.Length; - } - - public int GetLengthAsRefArray2() - { - ref int[] items = ref _items; - _ = TestCase.Add(items.Length); - return items.Length; - } - - public int GetLengthAsRefArray3() - { - ref int[] items = ref _items; - _ = TestCase.Add(items.Length); - _ = TestCase.Add(items.Length); - return items.Length; - } - - public int GetLengthAsRefArray4() - { - ref int[] items = ref _items; - _ = TestCase.Add(items.Length); - _ = TestCase.Add(items.Length); - _ = TestCase.Add(items.Length); - return items.Length; - } - - public int GetLengthAsRefArray5() - { - ref int[] items = ref _items; - _ = TestCase.Add(items.Length); - _ = TestCase.Add(items.Length); - _ = TestCase.Add(items.Length); - _ = TestCase.Add(items.Length); - return items.Length; - } - - public int GetLengthAsRefArray6() - { - ref int[] items = ref _items; - _ = TestCase.Add(items.Length); - _ = TestCase.Add(items.Length); - _ = TestCase.Add(items.Length); - _ = TestCase.Add(items.Length); - _ = TestCase.Add(items.Length); - return items.Length; - } - } - - [Benchmark] - public void RefToInt2() - { - var count = _testCase.GetCountAsRefCount2(); - DoNothing(count); - } - - [Benchmark] - public void RefToInt3() - { - var count = _testCase.GetCountAsRefCount3(); - DoNothing(count); - } - - [Benchmark] - public void RefToInt4() - { - var count = _testCase.GetCountAsRefCount4(); - DoNothing(count); - } - - [Benchmark] - public void RefToInt5() - { - var count = _testCase.GetCountAsRefCount5(); - DoNothing(count); - } - - [Benchmark(Baseline = true)] - public void IntInstanceMember2() - { - var count = _testCase.GetCountAsInstanceMember2(); - DoNothing(count); - } - - [Benchmark(Baseline = false)] - public void IntInstanceMember3() - { - var count = _testCase.GetCountAsInstanceMember3(); - DoNothing(count); - } - - [Benchmark(Baseline = false)] - public void IntInstanceMember4() - { - var count = _testCase.GetCountAsInstanceMember4(); - DoNothing(count); - } - - [Benchmark(Baseline = false)] - public void IntInstanceMember5() - { - var count = _testCase.GetCountAsInstanceMember5(); - DoNothing(count); - } - - [Benchmark] - public void RefToArray2() - { - var count = _testCase.GetLengthAsRefArray2(); - DoNothing(count); - } - - [Benchmark] - public void RefToArray3() - { - var count = _testCase.GetLengthAsRefArray3(); - DoNothing(count); - } - - [Benchmark] - public void RefToArray4() - { - var count = _testCase.GetLengthAsRefArray4(); - DoNothing(count); - } - - [Benchmark] - public void RefToArray5() - { - var count = _testCase.GetLengthAsRefArray5(); - DoNothing(count); - } - - [Benchmark] - public void RefToArray6() - { - var count = _testCase.GetLengthAsRefArray6(); - DoNothing(count); - } - - [Benchmark(Baseline = false)] - public void ArrayInstanceMember2() - { - var count = _testCase.GetLengthAsArray2(); - DoNothing(count); - } - - [Benchmark(Baseline = false)] - public void ArrayInstanceMember3() - { - var count = _testCase.GetLengthAsArray3(); - DoNothing(count); - } - - [Benchmark(Baseline = false)] - public void ArrayInstanceMember4() - { - var count = _testCase.GetLengthAsArray4(); - DoNothing(count); - } - - [Benchmark(Baseline = false)] - public void ArrayInstanceMember5() - { - var count = _testCase.GetLengthAsArray5(); - DoNothing(count); - } - - [Benchmark(Baseline = false)] - public void ArrayInstanceMember6() - { - var count = _testCase.GetLengthAsArray6(); - DoNothing(count); - } - - [Benchmark(Baseline = false)] - public void ArrayInstanceMemberLocalVar5() - { - var count = _testCase.GetLengthAsArrayLocalVar5(); - DoNothing(count); - } - - [Benchmark(Baseline = false)] - public void ArrayInstanceMemberLocalVar6() - { - var count = _testCase.GetLengthAsArrayLocalVar6(); - DoNothing(count); - } - } -} diff --git a/Recyclable.Collections.Benchmarks/POC/RoundBenchmarks.cs b/Recyclable.Collections.Benchmarks/POC/RoundBenchmarks.cs index e1d133b..dd8f60e 100644 --- a/Recyclable.Collections.Benchmarks/POC/RoundBenchmarks.cs +++ b/Recyclable.Collections.Benchmarks/POC/RoundBenchmarks.cs @@ -1,6 +1,7 @@ // Ignore Spelling: Poc using BenchmarkDotNet.Attributes; +using Collections.Benchmarks.Core; namespace Recyclable.Collections.Benchmarks.POC { @@ -11,7 +12,7 @@ namespace Recyclable.Collections.Benchmarks.POC WithTypecasting, } - public class RoundBenchmarks : PocBenchmarkBase + public class RoundBenchmarks : BaselineVsActualBenchmarkBase { [Params(RoundBenchmarkType.MathFloor)] public override RoundBenchmarkType BaseDataType { get => base.BaseDataType; set => base.BaseDataType = value; } @@ -23,17 +24,17 @@ namespace Recyclable.Collections.Benchmarks.POC public void RoundWithMathFloor() { - DoNothing((long)Math.Floor(TestObjectCount * OptimalParallelSearchStep)); + DoNothing.With((long)Math.Floor(TestObjectCount * OptimalParallelSearchStep)); } public void RoundWithMathRound() { - DoNothing((long)Math.Round(TestObjectCount * OptimalParallelSearchStep, 0)); + DoNothing.With((long)Math.Round(TestObjectCount * OptimalParallelSearchStep, 0)); } public void RoundWithTypeCasting() { - DoNothing((long)(TestObjectCount * OptimalParallelSearchStep)); + DoNothing.With((long)(TestObjectCount * OptimalParallelSearchStep)); } protected override Action GetTestMethod(RoundBenchmarkType benchmarkType) => benchmarkType switch diff --git a/Recyclable.Collections.Benchmarks/POC/RoundUpToPowerOf2vsOthers.cs b/Recyclable.Collections.Benchmarks/POC/RoundUpToPowerOf2Alternatives.cs similarity index 75% rename from Recyclable.Collections.Benchmarks/POC/RoundUpToPowerOf2vsOthers.cs rename to Recyclable.Collections.Benchmarks/POC/RoundUpToPowerOf2Alternatives.cs index 96906d9..51325db 100644 --- a/Recyclable.Collections.Benchmarks/POC/RoundUpToPowerOf2vsOthers.cs +++ b/Recyclable.Collections.Benchmarks/POC/RoundUpToPowerOf2Alternatives.cs @@ -1,10 +1,13 @@ +// Ignore Spelling: Poc + using BenchmarkDotNet.Attributes; +using Collections.Benchmarks.Core; namespace Recyclable.Collections.Benchmarks.POC { static class RoundUpToPowerOf2Alternatives { - private static readonly int[] PowersOfTwo = + private static readonly int[] _powersOfTwo = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, @@ -19,14 +22,14 @@ namespace Recyclable.Collections.Benchmarks.POC } // Find the smallest power of 2 greater than or equal to value using a lookup table - int index = Array.BinarySearch(PowersOfTwo, value); + int index = Array.BinarySearch(_powersOfTwo, value); if (index < 0) { // If value is not a power of 2, use the next power of 2 from the table index = ~index; } - return PowersOfTwo[index]; + return _powersOfTwo[index]; } public static int RightBitShifting(int value) @@ -74,7 +77,7 @@ namespace Recyclable.Collections.Benchmarks.POC IsPowOf2_GreaterEqual, } - public class RoundUpToPowerOf2vsOtherBenchmarks : PocBenchmarkBase + public class RoundUpToPowerOf2vsOtherBenchmarks : BaselineVsActualBenchmarkBase { // [Params(-850_000, 850_000)] [Params(-int.MaxValue, int.MaxValue)] @@ -89,42 +92,44 @@ namespace Recyclable.Collections.Benchmarks.POC private void BitOperations() { - DoNothing(System.Numerics.BitOperations.RoundUpToPowerOf2((uint)base.TestObjectCount)); + DoNothing.With(System.Numerics.BitOperations.RoundUpToPowerOf2((uint)base.TestObjectCount)); } private void RightBitShifting() { - DoNothing(RoundUpToPowerOf2Alternatives.RightBitShifting(TestObjectCount)); + DoNothing.With(RoundUpToPowerOf2Alternatives.RightBitShifting(TestObjectCount)); } private void LeftBitShifting() { - DoNothing(RoundUpToPowerOf2Alternatives.LeftBitShifting(TestObjectCount)); + DoNothing.With(RoundUpToPowerOf2Alternatives.LeftBitShifting(TestObjectCount)); } private void BinarySearch() { - DoNothing(RoundUpToPowerOf2Alternatives.BinarySearch(TestObjectCount)); + DoNothing.With(RoundUpToPowerOf2Alternatives.BinarySearch(TestObjectCount)); } private void IsPowOf2() { - DoNothing((TestObjectCount & (TestObjectCount - 1)) == 0 && TestObjectCount > 0); + DoNothing.With((TestObjectCount & (TestObjectCount - 1)) == 0 && TestObjectCount > 0); } private void IsPowOf2_GreaterThanFirst() { - DoNothing(TestObjectCount > 0 && (TestObjectCount & (TestObjectCount - 1)) == 0); + DoNothing.With(TestObjectCount > 0 && (TestObjectCount & (TestObjectCount - 1)) == 0); } private void IsPowOf2_WithIf() { - DoNothing(TestObjectCount > 0 ? (TestObjectCount & (TestObjectCount - 1)) == 0 : false); +#pragma warning disable IDE0075 // This is intentional + DoNothing.With(TestObjectCount > 0 ? (TestObjectCount & (TestObjectCount - 1)) == 0 : false); +#pragma warning restore IDE0075 } private void IsPowOf2_GreaterEqual() { - DoNothing(TestObjectCount >= 0 && TestObjectCount != 0 && (TestObjectCount & (TestObjectCount - 1)) == 0); + DoNothing.With(TestObjectCount >= 0 && TestObjectCount != 0 && (TestObjectCount & (TestObjectCount - 1)) == 0); } protected override Action? GetTestMethod(RoundUpToPowerOf2BenchmarkType benchmarkType) => benchmarkType switch diff --git a/Recyclable.Collections.Benchmarks/POC/SpanConstructorVsTypecasting.Benchmarks.cs b/Recyclable.Collections.Benchmarks/POC/SpanConstructorVsTypecasting.Benchmarks.cs deleted file mode 100644 index bee88e7..0000000 --- a/Recyclable.Collections.Benchmarks/POC/SpanConstructorVsTypecasting.Benchmarks.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System.Runtime.CompilerServices; -using BenchmarkDotNet.Attributes; - -namespace Recyclable.Collections.Benchmarks.POC -{ - public enum SpanConstructorVsTypecastingPocBenchmarkType - { - Unknown, - Constructor, - TypeCasting, - } - - [MemoryDiagnoser] - public class SpanConstructorVsTypecastingPocBenchmarks : PocBenchmarkBase - { - private int[]? TestData { get; set; } - - [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] - private void DoNothing(ReadOnlySpan span) { } - - [Params(SpanConstructorVsTypecastingPocBenchmarkType.TypeCasting)] - public override SpanConstructorVsTypecastingPocBenchmarkType BaseDataType { get => base.BaseDataType; set => base.BaseDataType = value; } - - [Params(SpanConstructorVsTypecastingPocBenchmarkType.Constructor)] - public override SpanConstructorVsTypecastingPocBenchmarkType DataType { get => base.DataType; set => base.DataType = value; } - - [Params(8)] - public override int TestObjectCount { get => base.TestObjectCount; set => base.TestObjectCount = value; } - - public static void Run() - { - var benchmark = new SpanConstructorVsTypecastingPocBenchmarks(); - benchmark.Setup(); - benchmark.Constructor(); - benchmark.TypeCasting(); - benchmark.Cleanup(); - } - - public void Constructor() - { - ReadOnlySpan span = new(TestData); - DoNothing(span); - } - - public void TypeCasting() - { - ReadOnlySpan span = TestData; - DoNothing(span); - } - - public override void Setup() - { - TestData = new int[TestObjectCount]; - base.Setup(); - } - - protected override Action? GetTestMethod(SpanConstructorVsTypecastingPocBenchmarkType benchmarkType) => benchmarkType switch - { - SpanConstructorVsTypecastingPocBenchmarkType.Constructor => Constructor, - SpanConstructorVsTypecastingPocBenchmarkType.TypeCasting => TypeCasting, - _ => throw CreateUnknownBenchmarkTypeException(benchmarkType), - }; - } -} \ No newline at end of file diff --git a/Recyclable.Collections.Benchmarks/POC/SpanConstructorVsTypecastingBenchmarks.cs b/Recyclable.Collections.Benchmarks/POC/SpanConstructorVsTypecastingBenchmarks.cs new file mode 100644 index 0000000..8d81157 --- /dev/null +++ b/Recyclable.Collections.Benchmarks/POC/SpanConstructorVsTypecastingBenchmarks.cs @@ -0,0 +1,63 @@ +// Ignore Spelling: Poc + +using BenchmarkDotNet.Attributes; +using Collections.Benchmarks.Core; + +namespace Recyclable.Collections.Benchmarks.POC +{ + public enum SpanConstructorVsTypecastingBenchmarkType + { + Unknown, + Constructor, + TypeCasting, + } + + [MemoryDiagnoser] + public class SpanConstructorVsTypecastingBenchmarks : BaselineVsActualBenchmarkBase + { + private int[]? TestData { get; set; } + + [Params(SpanConstructorVsTypecastingBenchmarkType.TypeCasting)] + public override SpanConstructorVsTypecastingBenchmarkType BaseDataType { get => base.BaseDataType; set => base.BaseDataType = value; } + + [Params(SpanConstructorVsTypecastingBenchmarkType.Constructor)] + public override SpanConstructorVsTypecastingBenchmarkType DataType { get => base.DataType; set => base.DataType = value; } + + [Params(8)] + public override int TestObjectCount { get => base.TestObjectCount; set => base.TestObjectCount = value; } + + public static void Run() + { + var benchmark = new SpanConstructorVsTypecastingBenchmarks(); + benchmark.Setup(); + benchmark.Constructor(); + benchmark.TypeCasting(); + benchmark.Cleanup(); + } + + public void Constructor() + { + ReadOnlySpan span = new(TestData); + DoNothing.With(span); + } + + public void TypeCasting() + { + ReadOnlySpan span = TestData; + DoNothing.With(span); + } + + public override void Setup() + { + TestData = new int[TestObjectCount]; + base.Setup(); + } + + protected override Action? GetTestMethod(SpanConstructorVsTypecastingBenchmarkType benchmarkType) => benchmarkType switch + { + SpanConstructorVsTypecastingBenchmarkType.Constructor => Constructor, + SpanConstructorVsTypecastingBenchmarkType.TypeCasting => TypeCasting, + _ => throw CreateUnknownBenchmarkTypeException(benchmarkType), + }; + } +} \ No newline at end of file diff --git a/Recyclable.Collections.Benchmarks/POC/SpanVsArrayBenchmarks.cs b/Recyclable.Collections.Benchmarks/POC/SpanVsArrayBenchmarks.cs index 944d396..f8dbdfb 100644 --- a/Recyclable.Collections.Benchmarks/POC/SpanVsArrayBenchmarks.cs +++ b/Recyclable.Collections.Benchmarks/POC/SpanVsArrayBenchmarks.cs @@ -1,6 +1,7 @@ // Ignore Spelling: Poc using BenchmarkDotNet.Attributes; +using Collections.Benchmarks.Core; namespace Recyclable.Collections.Benchmarks.POC { @@ -14,7 +15,7 @@ namespace Recyclable.Collections.Benchmarks.POC SpanSet } - public class SpanVsArrayBenchmarks : RecyclableBenchmarkBase + public class SpanVsArrayBenchmarks : DataDrivenBenchmarksBase { // [Params(SpanVsArrayBenchmarkType.ArrayGetWithVar, SpanVsArrayBenchmarkType.SpanGet)] // [Params(SpanVsArrayBenchmarkType.ArraySetWithVar, SpanVsArrayBenchmarkType.SpanSet)] @@ -46,7 +47,7 @@ namespace Recyclable.Collections.Benchmarks.POC var dataCount = TestObjectCount; for (int i = 0; i < dataCount; i++) { - DoNothing(data[i]); + DoNothing.With(data[i]); } } @@ -55,7 +56,7 @@ namespace Recyclable.Collections.Benchmarks.POC var dataCount = TestObjectCount; for (int i = 0; i < dataCount; i++) { - DoNothing(_testObjects![i]); + DoNothing.With(_testObjects![i]); } } @@ -65,7 +66,7 @@ namespace Recyclable.Collections.Benchmarks.POC Span data = new(_testObjects, 0, dataCount); for (int i = 0; i < dataCount; i++) { - DoNothing(data[i]); + DoNothing.With(data[i]); } } diff --git a/Recyclable.Collections.Benchmarks/Program.cs b/Recyclable.Collections.Benchmarks/Program.cs index a754215..ea7a441 100644 --- a/Recyclable.Collections.Benchmarks/Program.cs +++ b/Recyclable.Collections.Benchmarks/Program.cs @@ -1,6 +1,5 @@ using BenchmarkDotNet.Configs; using BenchmarkDotNet.Running; -using Recyclable.Collections.Benchmarks.POC; #pragma warning disable RCS1036, RCS1213, IDE0051 @@ -31,7 +30,7 @@ namespace Recyclable.Collections.Benchmarks foreach (var _ in Enumerable.Range(1, 1000)) { - // benchmark.RecyclableList_Create_WithCapacity(); + //benchmark.RecyclableList_Create_WithCapacity(); } benchmark.Cleanup(); @@ -39,26 +38,26 @@ namespace Recyclable.Collections.Benchmarks static void RunPocBenchmarks() { - _ = BenchmarkRunner.Run(BenchmarkConfig); - _ = BenchmarkRunner.Run(BenchmarkConfig); - _ = BenchmarkRunner.Run(BenchmarkConfig); - _ = BenchmarkRunner.Run(BenchmarkConfig); - _ = BenchmarkRunner.Run(BenchmarkConfig); - _ = BenchmarkRunner.Run(BenchmarkConfig); - _ = BenchmarkRunner.Run(BenchmarkConfig); - _ = BenchmarkRunner.Run(BenchmarkConfig); - _ = BenchmarkRunner.Run(BenchmarkConfig); - _ = BenchmarkRunner.Run(BenchmarkConfig); - _ = BenchmarkRunner.Run(BenchmarkConfig); - _ = BenchmarkRunner.Run(BenchmarkConfig); + //_ = BenchmarkRunner.Run(BenchmarkConfig); + //_ = BenchmarkRunner.Run(BenchmarkConfig); + //_ = BenchmarkRunner.Run(BenchmarkConfig); + //_ = BenchmarkRunner.Run(BenchmarkConfig); + //_ = BenchmarkRunner.Run(BenchmarkConfig); + //_ = BenchmarkRunner.Run(BenchmarkConfig); + //_ = BenchmarkRunner.Run(BenchmarkConfig); + //_ = BenchmarkRunner.Run(BenchmarkConfig); + //_ = BenchmarkRunner.Run(BenchmarkConfig); + //_ = BenchmarkRunner.Run(BenchmarkConfig); + //_ = BenchmarkRunner.Run(BenchmarkConfig); + //_ = BenchmarkRunner.Run(BenchmarkConfig); //ArraySizeLimitBenchmarks.Run(); } static void Main() { - RunRecyclableCollectionsBenchmarks(); - // RunPocBenchmarks(); + // RunRecyclableCollectionsBenchmarks(); + RunPocBenchmarks(); // RunSelectedBenchmarks(); // RunAssemblyBenchmarks(); } diff --git a/Recyclable.Collections.Benchmarks/Recyclable.Collections.Benchmarks.csproj b/Recyclable.Collections.Benchmarks/Recyclable.Collections.Benchmarks.csproj index 1bd552a..ae4917a 100644 --- a/Recyclable.Collections.Benchmarks/Recyclable.Collections.Benchmarks.csproj +++ b/Recyclable.Collections.Benchmarks/Recyclable.Collections.Benchmarks.csproj @@ -10,7 +10,7 @@ - + diff --git a/Recyclable.Collections/Recyclable.Collections.csproj b/Recyclable.Collections/Recyclable.Collections.csproj index 3decd82..f6ba18c 100644 --- a/Recyclable.Collections/Recyclable.Collections.csproj +++ b/Recyclable.Collections/Recyclable.Collections.csproj @@ -5,7 +5,7 @@ enable true Recyclable.Collections - 0.0.6 + 0.0.6.1 Marek Lemańczyk N/A Recyclable.Collections @@ -17,11 +17,14 @@ LICENSE.md README.md git - List<T> compatibility pack added for RecyclableList<T>. Various performance improvements and fixes. + List<T> compatibility code moved to Recyclable.Collections.Compatibility.List package. Cleanup. AnyCPU;x64 + + PreserveNewest + Always @@ -31,7 +34,6 @@ - - + diff --git a/Recyclable.Collections/RecyclableList.Compatibility.List.Find.cs b/Recyclable.Collections/RecyclableList.Compatibility.List.Find.cs deleted file mode 100644 index 00871d0..0000000 --- a/Recyclable.Collections/RecyclableList.Compatibility.List.Find.cs +++ /dev/null @@ -1,272 +0,0 @@ -using System.Numerics; - -namespace Recyclable.Collections -{ - [Obsolete("It'll be moved to Recyclable.Collections.Compatibility.List NuGet package in the next release.")] - public static class zRecyclableListCompatibilityListFind - { - public static bool Exists(this RecyclableList list, Predicate match) - { - int sourceItemsCount = list._count; - if (sourceItemsCount == 0) - { - return false; - } - - ReadOnlySpan sourceSpan = list._memoryBlock; - for (var itemIndex = 0; itemIndex < sourceItemsCount; itemIndex++) - { - if (match(sourceSpan[itemIndex])) - { - return true; - } - } - - return false; - } - - public static T? Find(this RecyclableList list, Predicate match) - { - int sourceItemsCount = list._count; - if (sourceItemsCount == 0) - { - return default; - } - - ReadOnlySpan sourceSpan = list._memoryBlock; - for (var itemIndex = 0; itemIndex < sourceItemsCount; itemIndex++) - { - if (match(sourceSpan[itemIndex])) - { - return sourceSpan[itemIndex]; - } - } - - return default; - } - - public static RecyclableList FindAll(this RecyclableList list, Predicate match) - { - int sourceItemsCount = list._count; - if (sourceItemsCount == 0) - { - return new(); - } - - ReadOnlySpan sourceSpan = list._memoryBlock; - RecyclableList result = new(sourceItemsCount >> 3); - Span resultSpan = result._memoryBlock; - int capacity = result._capacity, - resultItemsCount = 0; - - for (var itemIndex = 0; itemIndex < sourceItemsCount; itemIndex++) - { - if (match(sourceSpan[itemIndex])) - { - if (resultItemsCount + 1 > capacity) - { - capacity = checked((int)BitOperations.RoundUpToPowerOf2((uint)resultItemsCount + 1)); - _ = RecyclableListHelpers.EnsureCapacity(result, resultItemsCount, capacity); - resultSpan = result._memoryBlock; - } - - resultSpan[resultItemsCount++] = sourceSpan[itemIndex]; - } - } - - result._capacity = capacity; - result._count = resultItemsCount; - return result; - } - public static RecyclableList FindAllIndexes(this RecyclableList list, Predicate match) - { - int sourceItemsCount = list._count; - if (sourceItemsCount == 0) - { - return new(); - } - - ReadOnlySpan sourceSpan = list._memoryBlock; - RecyclableList result = new(sourceItemsCount >> 3); - Span resultSpan = result._memoryBlock; - int capacity = result._capacity, - resultItemsCount = 0; - - for (var itemIndex = 0; itemIndex < sourceItemsCount; itemIndex++) - { - if (match(sourceSpan[itemIndex])) - { - if (resultItemsCount + 1 > capacity) - { - capacity = checked((int)BitOperations.RoundUpToPowerOf2((uint)resultItemsCount + 1)); - _ = RecyclableListHelpers.EnsureCapacity(result, resultItemsCount, capacity); - resultSpan = result._memoryBlock; - } - - resultSpan[resultItemsCount++] = itemIndex; - } - } - - result._capacity = capacity; - result._count = resultItemsCount; - return result; - } - - public static int FindIndex(this RecyclableList list, int startIndex, int count, Predicate match) - { - int sourceItemsCount = list._count; - if (sourceItemsCount == 0 || startIndex >= sourceItemsCount) - { - return RecyclableDefaults.ItemNotFoundIndex; - } - - sourceItemsCount = Math.Min(sourceItemsCount, startIndex + sourceItemsCount); - ReadOnlySpan sourceSpan = list._memoryBlock; - for (var itemIndex = startIndex; itemIndex < sourceItemsCount; itemIndex++) - { - if (match(sourceSpan[itemIndex])) - { - return itemIndex; - } - } - - return RecyclableDefaults.ItemNotFoundIndex; - } - - public static int FindIndex(this RecyclableList list, int startIndex, Predicate match) - { - int sourceItemsCount = list._count; - if (sourceItemsCount == 0 || startIndex >= sourceItemsCount) - { - return RecyclableDefaults.ItemNotFoundIndex; - } - - sourceItemsCount = Math.Min(sourceItemsCount, startIndex + sourceItemsCount); - ReadOnlySpan sourceSpan = list._memoryBlock; - for (var itemIndex = startIndex; itemIndex < sourceItemsCount; itemIndex++) - { - if (match(sourceSpan[itemIndex])) - { - return itemIndex; - } - } - - return RecyclableDefaults.ItemNotFoundIndex; - } - - public static int FindIndex(this RecyclableList list, Predicate match) - { - int sourceItemsCount = list._count; - if (sourceItemsCount == 0) - { - return RecyclableDefaults.ItemNotFoundIndex; - } - - ReadOnlySpan sourceSpan = list._memoryBlock; - for (var itemIndex = 0; itemIndex < sourceItemsCount; itemIndex++) - { - if (match(sourceSpan[itemIndex])) - { - return itemIndex; - } - } - - return RecyclableDefaults.ItemNotFoundIndex; - } - - public static T? FindLast(this RecyclableList list, Predicate match) - { - if (list._count == 0) - { - return default; - } - - ReadOnlySpan sourceSpan = list._memoryBlock; - for (var itemIndex = list._count - 1; itemIndex >= 0; itemIndex--) - { - if (match(sourceSpan[itemIndex])) - { - return sourceSpan[itemIndex]; - } - } - - return default; - } - - public static int FindLastIndex(this RecyclableList list, int startIndex, int count, Predicate match) - { - if (count == 0) - { - if (startIndex != -1) - { - ThrowHelper.ThrowArgumentOutOfRangeException_Index(); - } - } - else if (count < 0 || startIndex - count + 1 < 0) - { - ThrowHelper.ThrowArgumentOutOfRangeException_Count(); - } - - if (startIndex < 0) - { - return RecyclableDefaults.ItemNotFoundIndex; - } - - int sourceItemsCount = count; // startIndex - count + 1 >= 0 ? count : startIndex + 1; - if (sourceItemsCount == 0) - { - return RecyclableDefaults.ItemNotFoundIndex; - } - - int lastItemIndex = startIndex - sourceItemsCount; - ReadOnlySpan sourceSpan = list._memoryBlock; - for (var itemIndex = startIndex; itemIndex > lastItemIndex; itemIndex--) - { - if (match(sourceSpan[itemIndex])) - { - return itemIndex; - } - } - - return RecyclableDefaults.ItemNotFoundIndex; - } - - public static int FindLastIndex(this RecyclableList list, int startIndex, Predicate match) - { - if (list._count == 0 || startIndex < 0) - { - return RecyclableDefaults.ItemNotFoundIndex; - } - - ReadOnlySpan sourceSpan = list._memoryBlock; - for (var itemIndex = startIndex; itemIndex >= 0; itemIndex--) - { - if (match(sourceSpan[itemIndex])) - { - return itemIndex; - } - } - - return RecyclableDefaults.ItemNotFoundIndex; - } - - public static int FindLastIndex(this RecyclableList list, Predicate match) - { - if (list._count == 0) - { - return RecyclableDefaults.ItemNotFoundIndex; - } - - ReadOnlySpan sourceSpan = list._memoryBlock; - for (var itemIndex = list._count - 1; itemIndex >= 0; itemIndex--) - { - if (match(sourceSpan[itemIndex])) - { - return itemIndex; - } - } - - return RecyclableDefaults.ItemNotFoundIndex; - } - } -} diff --git a/Recyclable.Collections/RecyclableList.Compatibility.List.IndexOf.cs b/Recyclable.Collections/RecyclableList.Compatibility.List.IndexOf.cs deleted file mode 100644 index 09aa8d4..0000000 --- a/Recyclable.Collections/RecyclableList.Compatibility.List.IndexOf.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace Recyclable.Collections -{ - [Obsolete("It'll be moved to Recyclable.Collections.Compatibility.List NuGet package in the next release.")] - public static class zRecyclableListCompatibilityListIndexOf - { - public static int IndexOf(this RecyclableList list, T item, int index) => list._count != 0 - ? Array.IndexOf(list._memoryBlock, item, index, list._count - index) - : RecyclableDefaults.ItemNotFoundIndex; - - public static int IndexOf(this RecyclableList list, T item, int index, int count) => list._count != 0 - ? Array.IndexOf(list._memoryBlock, item, index, count) - : RecyclableDefaults.ItemNotFoundIndex; - - public static int LastIndexOf(this RecyclableList list, T item) => list._count != 0 - ? Array.LastIndexOf(list._memoryBlock, item, list._count - 1) - : RecyclableDefaults.ItemNotFoundIndex; - - public static int LastIndexOf(this RecyclableList list, T item, int index) => list._count != 0 - ? Array.LastIndexOf(list._memoryBlock, item, index) - : RecyclableDefaults.ItemNotFoundIndex; - - public static int LastIndexOf(this RecyclableList list, T item, int index, int count) => list._count != 0 - ? Array.LastIndexOf(list._memoryBlock, item, index, count) - : RecyclableDefaults.ItemNotFoundIndex; - } -} diff --git a/Recyclable.Collections/RecyclableList.Compatibility.List.InsertRange.cs b/Recyclable.Collections/RecyclableList.Compatibility.List.InsertRange.cs deleted file mode 100644 index 27a1107..0000000 --- a/Recyclable.Collections/RecyclableList.Compatibility.List.InsertRange.cs +++ /dev/null @@ -1,358 +0,0 @@ -using System.Collections; -using System.Numerics; -using System.Runtime.CompilerServices; - -namespace Recyclable.Collections -{ - [Obsolete("It'll be moved to Recyclable.Collections.Compatibility.List NuGet package in the next release.")] - public static class zRecyclableListCompatibilityListInsertRange - { - private static void InsertRangeEnumerated(this RecyclableList list, int index, IEnumerable items, int growByCount) - { - var enumerator = items.GetEnumerator(); - if (!enumerator.MoveNext()) - { - return; - } - - int capacity = list._capacity, - added = 0, - available = capacity - list._count, - i, - movingBlockLength = list._count - index; - - T[] memoryBlock = list._memoryBlock; - if (available > 0) - { - Array.Copy(memoryBlock, index, memoryBlock, capacity - movingBlockLength, movingBlockLength); - } - - Span memorySpan = memoryBlock; - do - { - if (index + available + movingBlockLength > capacity) - { - var capacityBeforeIncrease = capacity; - capacity = checked((int)BitOperations.RoundUpToPowerOf2((uint)(capacity + growByCount))); - _ = RecyclableListHelpers.EnsureCapacity(list, memoryBlock.Length, capacity); - memorySpan = memoryBlock = list._memoryBlock; - available = capacity - index - movingBlockLength; - Array.Copy(memoryBlock, capacityBeforeIncrease - movingBlockLength, memoryBlock, capacity - movingBlockLength, movingBlockLength); - } - - for (i = 0; i < available; i++) - { - memorySpan[index++] = enumerator.Current; - if (!enumerator.MoveNext()) - { - added++; - break; - } - } - - added += i; - } - while (i == available); - - if (i != available) - { - Array.Copy(memoryBlock, capacity - movingBlockLength, memoryBlock, index, movingBlockLength); - if (RecyclableList._needsClearing) - { - Array.Clear(memoryBlock, capacity - movingBlockLength, movingBlockLength); - } - } - - list._count += added; - list._capacity = capacity; - } - - private static void InsertRangeWithKnownCount(this RecyclableList list, int index, IEnumerable items, int currentItemsCount, int requiredAdditionalCapacity) - { - list._capacity = RecyclableListHelpers.EnsureCapacity(list, currentItemsCount, checked((int)BitOperations.RoundUpToPowerOf2((uint)(currentItemsCount + requiredAdditionalCapacity)))); - - Array.Copy(list._memoryBlock, index, list._memoryBlock, index + requiredAdditionalCapacity, list._count - index); - Span memorySpan = list._memoryBlock; - foreach (var item in items) - { - memorySpan[index++] = item; - } - - list._count += requiredAdditionalCapacity; - list._version++; - } - - [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] - public static void InsertRange(this RecyclableList list, int index, in Array items) - { - if (list._capacity < list._count + items.Length) - { - list._capacity = RecyclableListHelpers.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + items.Length)))); - } - - T[] memoryBlock = list._memoryBlock; - Array.Copy(memoryBlock, index, memoryBlock, index + items.Length, list._count - index); - Array.Copy(items, items.GetLowerBound(0), memoryBlock, index, items.Length); - list._count += items.Length; - list._version++; - } - - [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] - public static void InsertRange(this RecyclableList list, int index, in T[] items) - { - if (list._capacity < list._count + items.Length) - { - list._capacity = RecyclableListHelpers.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + items.Length)))); - } - - T[] memoryBlock = list._memoryBlock; - Array.Copy(memoryBlock, index, memoryBlock, index + items.Length, list._count - index); - new ReadOnlySpan(items).CopyTo(new Span(memoryBlock, index, items.Length)); - list._count += items.Length; - list._version++; - } - - [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] - public static void InsertRange(this RecyclableList list, int index, ReadOnlySpan items) - { - if (list._capacity < list._count + items.Length) - { - list._capacity = RecyclableListHelpers.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + items.Length)))); - } - - T[] memoryBlock = list._memoryBlock; - Array.Copy(memoryBlock, index, memoryBlock, index + items.Length, list._count - index); - items.CopyTo(new Span(memoryBlock, index, items.Length)); - list._count += items.Length; - list._version++; - } - - [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] - public static void InsertRange(this RecyclableList list, int index, Span items) - { - if (list._capacity < list._count + items.Length) - { - list._capacity = RecyclableListHelpers.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + items.Length)))); - } - - T[] memoryBlock = list._memoryBlock; - Array.Copy(memoryBlock, index, memoryBlock, index + items.Length, list._count - index); - items.CopyTo(new Span(memoryBlock, index, items.Length)); - list._count += items.Length; - list._version++; - } - - [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] - public static void InsertRange(this RecyclableList list, int index, List items) - { - if (list._capacity < list._count + items.Count) - { - list._capacity = RecyclableListHelpers.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + items.Count)))); - } - - T[] memoryBlock = list._memoryBlock; - Array.Copy(memoryBlock, index, memoryBlock, index + items.Count, list._count - index); - items.CopyTo(memoryBlock, index); - list._count += items.Count; - list._version++; - } - - [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] - public static void InsertRange(this RecyclableList list, int index, ICollection items) - { - if (list._capacity < list._count + items.Count) - { - list._capacity = RecyclableListHelpers.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + items.Count)))); - } - - T[] memoryBlock = list._memoryBlock; - Array.Copy(memoryBlock, index, memoryBlock, index + items.Count, list._count - index); - items.CopyTo(list._memoryBlock, index); - list._count += items.Count; - list._version++; - } - - [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] - public static void InsertRange(this RecyclableList list, int index, ICollection items) - { - if (list._capacity < list._count + items.Count) - { - list._capacity = RecyclableListHelpers.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + items.Count)))); - } - - T[] memoryBlock = list._memoryBlock; - Array.Copy(memoryBlock, index, memoryBlock, index + items.Count, list._count - index); - items.CopyTo(memoryBlock, index); - list._count += items.Count; - list._version++; - } - - [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] - public static void InsertRange(this RecyclableList list, int index, RecyclableList items) - { - if (list._capacity < list._count + items._count) - { - list._capacity = RecyclableListHelpers.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + items._count)))); - } - - T[] memoryBlock = list._memoryBlock; - Array.Copy(memoryBlock, index, memoryBlock, index + items.Count, list._count - index); - new ReadOnlySpan(items._memoryBlock, 0, items._count).CopyTo(new(list._memoryBlock, index, items._count)); - list._count += items._count; - list._version++; - } - - [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] - public static void InsertRange(this RecyclableList list, int index, RecyclableLongList items) - { - if (items._longCount == 0) - { - return; - } - - int oldCount = list._count; - long sourceItemsCount = items._longCount; - if (oldCount + sourceItemsCount > int.MaxValue) - { - ThrowHelper.ThrowArgumentOutOfRangeException(nameof(items), $"The total number of items in source and target table exceeds the maximum capacity of {nameof(RecyclableList)}, equal {int.MaxValue}. Please consider using {nameof(RecyclableLongList)}, instead"); - } - - int targetCapacity = oldCount + (int)sourceItemsCount; - if (list._capacity < targetCapacity) - { - list._capacity = RecyclableListHelpers.EnsureCapacity(list, oldCount, checked((int)BitOperations.RoundUpToPowerOf2((uint)targetCapacity))); - } - - T[] memoryBlock = list._memoryBlock; - Array.Copy(memoryBlock, index, memoryBlock, index + items.Count, oldCount - index); - Span targetSpan = new(list._memoryBlock, index, list._capacity - index), - itemsSpan; - - int blockIndex, - sourceBlockSize = items._blockSize, - lastBlockIndex = (int)(sourceItemsCount >> items._blockSizePow2BitShift) - 1; - - for (blockIndex = 0; blockIndex <= lastBlockIndex; blockIndex++) - { - itemsSpan = new(items._memoryBlocks[blockIndex], 0, sourceBlockSize); - itemsSpan.CopyTo(targetSpan); - targetSpan = targetSpan[sourceBlockSize..]; - } - - if (blockIndex == 0) - { - itemsSpan = new(items._memoryBlocks[blockIndex], 0, (int)sourceItemsCount); - itemsSpan.CopyTo(targetSpan); - } - else if (blockIndex <= items._lastBlockWithData) - { - itemsSpan = new(items._memoryBlocks[blockIndex], 0, items._nextItemIndex > 0 ? items._nextItemIndex : sourceBlockSize); - itemsSpan.CopyTo(targetSpan); - } - - list._count = targetCapacity; - list._version++; - } - - public static IEnumerator InsertRange(this RecyclableList list, int index, IEnumerable source, int growByCount = RecyclableDefaults.MinPooledArrayLength) - { - int targetItemIndex = list._count; - Span memorySpan; - - int i; - var enumerator = source.GetEnumerator(); - - int capacity = list._capacity; - memorySpan = list._memoryBlock; - if (enumerator.MoveNext()) - { - int available = capacity - targetItemIndex; - do - { - if (targetItemIndex + growByCount > capacity) - { - capacity = RecyclableListHelpers.EnsureCapacity(list, targetItemIndex, checked((int)BitOperations.RoundUpToPowerOf2((uint)(targetItemIndex + growByCount)))); - memorySpan = list._memoryBlock; - available = capacity - targetItemIndex; - } - - for (i = 0; i < available; i++) - { - memorySpan[targetItemIndex++] = (T)enumerator.Current; - if (!enumerator.MoveNext()) - { - break; - } - } - } - while (i >= available); - } - - list._capacity = capacity; - list._count = targetItemIndex; - return enumerator; - } - - public static void InsertRange(this RecyclableList list, int index, IReadOnlyList items) - { - int sourceItemsCount = items.Count; - if (list._capacity < list._count + sourceItemsCount) - { - list._capacity = RecyclableListHelpers.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + sourceItemsCount)))); - } - - Span memorySpan = new(list._memoryBlock, list._count, sourceItemsCount); - for (var sourceItemIndex = 0; sourceItemIndex < sourceItemsCount; sourceItemIndex++) - { - memorySpan[sourceItemIndex] = items[sourceItemIndex]; - } - - list._count += sourceItemsCount; - } - - [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] - public static void InsertRange(this RecyclableList list, int index, IEnumerable items, int growByCount = RecyclableDefaults.MinPooledArrayLength) - { - if (items is RecyclableList sourceRecyclableList) - { - InsertRange(list, index, sourceRecyclableList); - } - else if (items is RecyclableLongList sourceRecyclableLongList) - { - InsertRange(list, index, sourceRecyclableLongList); - } - else if (items is T[] sourceArray) - { - InsertRange(list, index, sourceArray); - } - else if (items is Array sourceArrayWithObjects) - { - InsertRange(list, index, sourceArrayWithObjects); - } - else if (items is List sourceList) - { - InsertRange(list, index, sourceList); - } - else if (items is ICollection sourceICollection) - { - InsertRange(list, index, sourceICollection); - } - else if (items is ICollection sourceICollectionWithObjects) - { - InsertRange(list, index, sourceICollectionWithObjects); - } - else if (items is IReadOnlyList sourceIReadOnlyList) - { - InsertRange(list, index, sourceIReadOnlyList); - } - else if (items.TryGetNonEnumeratedCount(out var requiredAdditionalCapacity) && requiredAdditionalCapacity != 0) - { - InsertRangeWithKnownCount(list, index, items, list._count, requiredAdditionalCapacity); - } - else - { - InsertRangeEnumerated(list, index, items, growByCount); - } - } - } -} \ No newline at end of file diff --git a/Recyclable.Collections/RecyclableList.Compatibility.List.cs b/Recyclable.Collections/RecyclableList.Compatibility.List.cs deleted file mode 100644 index ba3e662..0000000 --- a/Recyclable.Collections/RecyclableList.Compatibility.List.cs +++ /dev/null @@ -1,214 +0,0 @@ -using System.Collections.ObjectModel; -using System.Numerics; -using Recyclable.Collections.Pools; - -namespace Recyclable.Collections -{ - - [Obsolete("It'll be moved to Recyclable.Collections.Compatibility.List NuGet package in the next release.")] - public static class zRecyclableListCompatibilityList - { - public static ReadOnlyCollection AsReadOnly(this RecyclableList list) => new(list); - - public static int BinarySearch(this RecyclableList list, T item) - => Array.BinarySearch(list._memoryBlock, 0, list._count, item); - - public static int BinarySearch(this RecyclableList list, T item, IComparer? comparer) - => Array.BinarySearch(list._memoryBlock, 0, list._count, item, comparer); - - public static int BinarySearch(this RecyclableList list, int index, int count, T item, IComparer? comparer) - => Array.BinarySearch(list._memoryBlock, index, count, item, comparer); - - public static RecyclableList ConvertAll(this RecyclableList list, Converter converter) - { - int itemsCount = list._count; - if (itemsCount == 0) - { - return new(); - } - - RecyclableList result = new(itemsCount); - TOutput[] resultSpan = result._memoryBlock; - ReadOnlySpan sourceSpan = list._memoryBlock; - for (int bufferIndex = 0; bufferIndex < itemsCount; bufferIndex++) - { - resultSpan[bufferIndex] = converter(sourceSpan[bufferIndex]); - } - - result._count = itemsCount; - return result; - } - - public static void CopyTo(this RecyclableList list, T[] array) => Array.Copy(list._memoryBlock, array, list._count); - - public static void CopyTo(this RecyclableList list, int index, T[] array, int arrayIndex, int count) => Array.Copy(list._memoryBlock, index, array, arrayIndex, count); - - public static void ForEach(this RecyclableList list, Action action) - { - int sourceItemsCount = list._count; - if (sourceItemsCount == 0) - { - return; - } - - ReadOnlySpan sourceSpan = list._memoryBlock; - for (var itemIndex = 0; itemIndex < sourceItemsCount; itemIndex++) - { - action(sourceSpan[itemIndex]); - } - } - - public static RecyclableList GetRange(this RecyclableList list, int index, int count) - { - int sourceItemsCount = index + count <= list._count ? count : list._count - index; - if (sourceItemsCount <= 0) - { - return new(); - } - - ReadOnlySpan sourceSpan = list._memoryBlock; - RecyclableList result = new(sourceItemsCount); - Span targetSpan = result._memoryBlock; - int resultItemsCount = 0; - sourceItemsCount += index; - for (var itemIndex = index; itemIndex < sourceItemsCount; itemIndex++) - { - targetSpan[resultItemsCount++] = sourceSpan[itemIndex]; - } - - result._count = resultItemsCount; - return result; - } - - public static int RemoveAll(this RecyclableList list, Predicate match) - { - using var allIndexes = list.FindAllIndexes(match); - int foundItemsCount = allIndexes._count; - if (foundItemsCount == 0) - { - return foundItemsCount; - } - - for (int removed = 0; removed < foundItemsCount; removed++) - { - var indexToRemove = allIndexes[removed] - removed; - Array.Copy(list._memoryBlock, indexToRemove + 1, list._memoryBlock, indexToRemove, list._count - indexToRemove - removed - 1); - } - - if (RecyclableList._needsClearing) - { - Array.Clear(list._memoryBlock, list._count - foundItemsCount, foundItemsCount); - } - - list._count -= foundItemsCount; - list._version++; - return foundItemsCount; - } - - public static void RemoveRange(this RecyclableList list, int index, int count) - { - int oldCount = list._count; - count = count - index + 1 <= oldCount ? count : oldCount - index + 1; - if (count == 0) - { - return; - } - - if (index + count < oldCount) - { - Array.Copy(list._memoryBlock, index + count, list._memoryBlock, index, oldCount - count - index); - } - - if (RecyclableList._needsClearing) - { - Array.Clear(list._memoryBlock, oldCount - count, count); - } - - list._count -= count; - list._version++; - } - - public static void Reverse(this RecyclableList list) - { - Array.Reverse(list._memoryBlock, 0, list._count); - list._version++; - } - - public static void Reverse(this RecyclableList list, int index, int count) - { - Array.Reverse(list._memoryBlock, index, count); - list._version++; - } - - public static void Sort(this RecyclableList list) - { - Array.Sort(list._memoryBlock, 0, list._count); - list._version++; - } - - public static void Sort(this RecyclableList list, Comparison comparison) - { - Array.Sort(list._memoryBlock, 0, list._count, new ComparisonToComparerAdapter(comparison)); - list._version++; - } - - public static void Sort(this RecyclableList list, IComparer? comparer) - { - Array.Sort(list._memoryBlock, 0, list._count, comparer); - list._version++; - } - - public static void Sort(this RecyclableList list, int index, int count, IComparer? comparer) - { - Array.Sort(list._memoryBlock, index, count, comparer); - list._version++; - } - - public static T[] ToArray(this RecyclableList list) - { - T[] result = new T[list._count]; - new ReadOnlySpan(list._memoryBlock, 0, list._count).CopyTo(result); - return result; - } - - public static void TrimExcess(this RecyclableList list) - { - var requiredCapacity = list._count >= RecyclableDefaults.InitialCapacity ? list._count : RecyclableDefaults.InitialCapacity; - - T[] oldMemoryBlock = list._memoryBlock; - T[] result = requiredCapacity >= RecyclableDefaults.MinPooledArrayLength && BitOperations.IsPow2(requiredCapacity) - ? RecyclableArrayPool.RentShared(requiredCapacity) - : new T[requiredCapacity]; - - new ReadOnlySpan(oldMemoryBlock, 0, list._count).CopyTo(result); - - if (oldMemoryBlock.Length >= RecyclableDefaults.MinPooledArrayLength) - { - RecyclableArrayPool.ReturnShared(oldMemoryBlock, RecyclableList._needsClearing); - } - - list._memoryBlock = result; - list._capacity = requiredCapacity; - } - - public static bool TrueForAll(this RecyclableList list, Predicate match) - { - int sourceItemsCount = list._count; - if (sourceItemsCount == 0) - { - return false; - } - - ReadOnlySpan sourceSpan = list._memoryBlock; - for (var itemIndex = 0; itemIndex < sourceItemsCount; itemIndex++) - { - if (!match(sourceSpan[itemIndex])) - { - return false; - } - } - - return true; - } - } -} diff --git a/Recyclable.CollectionsTests/CustomIList.cs b/Recyclable.CollectionsTests/CustomIList.cs deleted file mode 100644 index 81acead..0000000 --- a/Recyclable.CollectionsTests/CustomIList.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Collections; - -namespace Recyclable.CollectionsTests -{ - public class CustomIList : IList - { - protected List _list; - - public CustomIList() - { - _list = new List(); - } - - public CustomIList(IEnumerable items) - { - _list = new List(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 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(); - } -} \ No newline at end of file diff --git a/Recyclable.CollectionsTests/EnumerableWithoutCount.cs b/Recyclable.CollectionsTests/EnumerableWithoutCount.cs deleted file mode 100644 index 34df3e9..0000000 --- a/Recyclable.CollectionsTests/EnumerableWithoutCount.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.Collections; - -namespace Recyclable.CollectionsTests -{ - public class EnumerableWithoutCount : IEnumerable - { - private readonly IEnumerable _testData; - - public EnumerableWithoutCount(IEnumerable testData) - { - _testData = testData; - } - - public IEnumerator GetEnumerator() => _testData.GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() => _testData.GetEnumerator(); - } -} \ No newline at end of file diff --git a/Recyclable.CollectionsTests/Recyclable.CollectionsTests.csproj b/Recyclable.CollectionsTests/Recyclable.CollectionsTests.csproj index 2be9788..bd758b7 100644 --- a/Recyclable.CollectionsTests/Recyclable.CollectionsTests.csproj +++ b/Recyclable.CollectionsTests/Recyclable.CollectionsTests.csproj @@ -9,20 +9,19 @@ - - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Recyclable.CollectionsTests/RecyclableListTests.cs b/Recyclable.CollectionsTests/RecyclableListTests.cs index 9271a24..828ab17 100644 --- a/Recyclable.CollectionsTests/RecyclableListTests.cs +++ b/Recyclable.CollectionsTests/RecyclableListTests.cs @@ -1,9 +1,8 @@ using FluentAssertions; using Recyclable.Collections; +using Recyclable.Collections.TestData; using Recyclable.Collections.Linq; -using Recyclable.Collections.Pools; using System.Collections; -using System.Numerics; #pragma warning disable xUnit1026, RCS1163, IDE0060, RCS1235 @@ -501,22 +500,6 @@ namespace Recyclable.CollectionsTests } } - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))] - public void ConvertAllShouldConvertAllItems(string testCase, IEnumerable testData, int itemsCount) - { - // Prepare - using var list = new RecyclableList(testData, itemsCount); - var expectedData = testData.ToList().ConvertAll(item => item + 0.1); - - // Act - using var actual = list.ConvertAll(item => item + 0.1); - - // Validate - _ = actual.Count.Should().Be(itemsCount); - _ = actual.Should().Equal(expectedData); - } - [Theory] [MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))] public void CopyToShouldCopyAllItemsInTheCorrectOrder(string testCase, IEnumerable testData, int itemsCount) @@ -535,24 +518,6 @@ namespace Recyclable.CollectionsTests _ = copiedItems.Should().Equal(expectedData); } - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))] - public void CopyToShouldCopyAllItemsInTheCorrectOrderWhenFromStart(string testCase, IEnumerable testData, int itemsCount) - { - // Prepare - using var list = new RecyclableList(testData, itemsCount); - long[] copiedItems = new long[itemsCount]; - - // Act - list.CopyTo(copiedItems); - - // Validate - long[] expectedData = new long[itemsCount]; - testData.ToList().CopyTo(expectedData); - - _ = copiedItems.Should().Equal(testData); - } - [Theory] [MemberData(nameof(RecyclableLongListTestData.SourceRefDataVariants), MemberType = typeof(RecyclableLongListTestData))] public void DisposeShouldClearItemsWhenReferenceType(string testCase, IEnumerable testData, int itemsCount) @@ -632,373 +597,6 @@ namespace Recyclable.CollectionsTests _ = yieldedItems.Should().Equal(expectedData); } - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] - public void ExistsShouldFindAllItems(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) - { - _ = testData.Any().Should().BeTrue("we need items on the list that we can look for"); - - // Prepare - using var list = new RecyclableList(testData, itemsCount); - var expectedData = testData.ToList(); - - foreach (var itemIndex in itemIndexes) - { - var expectedItem = expectedData[(int)itemIndex]; - var expected = expectedData.Exists(item => item == expectedItem); - - // Act - var actual = list.Exists(item => item == expectedItem); - - // Validate - _ = actual.Should().Be(expected); - } - } - - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] - public void ExistsShouldNotFindNonExistingItems(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) - { - _ = testData.Any().Should().BeTrue("we need items on the list that we can look for"); - - // Prepare - using var list = new RecyclableList(testData, itemsCount); - var expectedData = testData.ToList(); - - foreach (var itemIndex in itemIndexes) - { - var expectedItem = expectedData[(int)itemIndex]; - var expected = expectedData.Exists(item => item == -expectedItem); - - // Act - var actual = list.Exists(item => item == -expectedItem); - - // Validate - _ = actual.Should().Be(expected); - } - } - - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] - public void FindAllIndexesShouldReturnCorrectIndexes(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) - { - //* There is no equivalent of .FindAllIndexes in List, so no comparison here. - - // Prepare - using var list = new RecyclableList(testData, itemsCount); - - foreach (var itemIndex in itemIndexes) - { - // Act - using var actual = list.FindAllIndexes(item => item == itemIndex + 1); - - // Validate - _ = actual.Count.Should().Be(1); - if (itemsCount > 0) - { - _ = actual.Count.Should().Be(1); - _ = actual.Should().AllSatisfy(x => x.Should().Be((int)itemIndex)); - } - } - } - - [Theory] - [MemberData(nameof(RecyclableLongListTestData.ItemsCountTestCases), MemberType = typeof(RecyclableLongListTestData))] - public void FindAllShouldReturnCorrectIndexes(int itemsCount) - { - const int expectedItem = 1; - - // Prepare - var testData = Enumerable.Range(0, itemsCount).Select(value => value % 2 == 0 ? expectedItem : -expectedItem); - using var list = new RecyclableList(testData, itemsCount); - - // Act - using var actual = list.FindAll(x => x == expectedItem); - - // Validate - var expectedData = testData.ToList().FindAll(x => x == expectedItem); - - _ = actual.Count.Should().Be(expectedData.Count); - _ = actual.Should().Equal(expectedData); - if (expectedData.Count > 0) - { - _ = actual.Should().AllSatisfy(x => x.Should().Be(expectedItem)).And.Equal(expectedData); - } - } - - [Theory] - [MemberData(nameof(RecyclableLongListTestData.ItemsCountTestCases), MemberType = typeof(RecyclableLongListTestData))] - public void FindAllShouldNotFindNonExistingItems(int itemsCount) - { - const int expectedItem = 1; - - // Prepare - var testData = Enumerable.Range(0, itemsCount).Select(_ => expectedItem); - using var list = new RecyclableList(testData, itemsCount); - - // Act - using var foundItems = list.FindAll(x => x == -expectedItem); - - // Validate - var expectedData = testData.ToList().FindAll(x => x == -expectedItem); - - _ = foundItems.Count.Should().Be(expectedData.Count); - _ = foundItems.Should().Equal(expectedData); - } - - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] - public void FindIndexShouldReturnCorrectIndexes(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) - { - // Prepare - using var list = new RecyclableList(testData, itemsCount); - var expectedData = testData.ToList(); - - foreach (var itemIndex in itemIndexes) - { - var expectedItem = expectedData[(int)itemIndex]; - - // Act - var actual = list.FindIndex(item => item == expectedItem); - - // Validate - var expected = expectedData.FindIndex(item => item == expectedItem); - - _ = actual.Should().Be((int)itemIndex).And.Be(expected); - } - } - - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] - public void FindIndexShouldReturnCorrectIndexesWhenConstrainedCount(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) - { - // Prepare - using var list = new RecyclableList(testData, itemsCount); - var expectedData = testData.ToList(); - - foreach (var itemIndex in itemIndexes) - { - var expectedItem = expectedData[(int)itemIndex]; - var expected = expectedData.FindIndex((int)itemIndex, (int)(itemsCount - itemIndex), item => item == expectedItem); - - // Act - var actual = list.FindIndex((int)itemIndex, (int)(itemsCount - itemIndex), item => item == expectedItem); - - // Validate - _ = actual.Should().Be((int)itemIndex).And.Be(expected); - } - } - - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] - public void FindIndexShouldReturnCorrectIndexesWhenConstrainedIndex(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) - { - // Prepare - using var list = new RecyclableList(testData, itemsCount); - var expectedData = testData.ToList(); - - foreach (var itemIndex in itemIndexes) - { - var expectedItem = expectedData[(int)itemIndex]; - var expected = expectedData.FindIndex(Math.Min(1, (int)itemIndex), item => item == expectedItem); - - // Act - var actual = list.FindIndex(Math.Min(1, (int)itemIndex), item => item == expectedItem); - - // Validate - _ = actual.Should().Be((int)itemIndex).And.Be(expected); - } - } - - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] - public void FindLastIndexShouldReturnCorrectIndexes(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) - { - // Prepare - using var list = new RecyclableList(testData, itemsCount); - var expectedData = testData.ToList(); - - foreach (var itemIndex in itemIndexes) - { - var expectedItem = expectedData[(int)itemIndex]; - var expected = expectedData.FindLastIndex(x => x == expectedItem); - - // Act - var actual = list.FindLastIndex(x => x == expectedItem); - - // Validate - _ = actual.Should().Be((int)itemIndex).And.Be(expected); - } - } - - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] - public void FindLastIndexShouldReturnCorrectIndexesWhenConstrainedCount(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) - { - // Prepare - using var list = new RecyclableList(testData, itemsCount); - var expectedData = testData.ToList(); - - foreach (var itemIndex in itemIndexes) - { - var expectedItem = expectedData[(int)itemIndex]; - - // Act & Validate - var expected = expectedData.FindLastIndex(itemsCount - 1, itemsCount, x => x == expectedItem); - _ = list.FindLastIndex(itemsCount - 1, itemsCount, x => x == expectedItem).Should().Be((int)itemIndex).And.Be(expected); - } - } - - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] - public void FindLastIndexShouldReturnCorrectIndexesWhenConstrainedIndex(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) - { - // Prepare - using var list = new RecyclableList(testData, itemsCount); - var expectedData = testData.ToList(); - - foreach (var itemIndex in itemIndexes) - { - var expectedItem = expectedData[(int)itemIndex]; - var expected = expectedData.FindLastIndex(itemsCount - 1, x => x == expectedItem); - - // Act - var actual = list.FindLastIndex(itemsCount - 1, x => x == expectedItem); - - // Validate - _ = actual.Should().Be((int)itemIndex).And.Be(expected); - } - } - - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] - public void FindLastIndexShouldThrowArgumentOutOfRange(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) - { - // Prepare - using var list = new RecyclableList(testData, itemsCount); - var expectedData = testData.ToList(); - - foreach (var itemIndex in itemIndexes) - { - var expectedItem = expectedData[(int)itemIndex]; - int expected = int.MinValue; - - // Act & Validate - if (itemsCount - 1 != -1) - { - Assert.Throws(() => expected = expectedData.FindLastIndex(itemsCount - 1, itemsCount + 3, x => x == expectedItem)); - Assert.Throws(() => _ = list.FindLastIndex(itemsCount - 1, itemsCount + 3, x => x == expectedItem).Should().Be((int)itemIndex).And.Be(expected)); - } - else - { - expected = expectedData.FindLastIndex(itemsCount - 1, itemsCount + 3, x => x == expectedItem); - _ = list.FindLastIndex(itemsCount - 1, itemsCount + 3, x => x == expectedItem).Should().Be((int)itemIndex).And.Be(expected); - } - } - } - - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] - public void FindLastShouldReturnCorrectItem(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) - { - // Prepare - using var list = new RecyclableList(testData, itemsCount); - var expectedData = testData.ToList(); - - foreach (var itemIndex in itemIndexes) - { - var expectedItem = expectedData[(int)itemIndex]; - var expected = expectedData.FindLast(item => item == expectedItem); - - // Act - var actual = list.FindLast(item => item == expectedItem); - - // Validate - _ = actual.Should().Be(expectedData[(int)itemIndex]).And.Be(expected); - } - } - - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] - public void FindShouldFindAllItems(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) - { - _ = testData.Any().Should().BeTrue("we need items on the list that we can look for"); - - // Prepare - using var list = new RecyclableList(testData, itemsCount); - var expectedData = testData.ToList(); - - foreach (var itemIndex in itemIndexes) - { - long expectedItem = expectedData[(int)itemIndex]; - var expected = expectedData.Find(item => item == expectedItem); - - // Act - var actual = list.Find(item => item == expectedData[(int)itemIndex]); - - // Validate - _ = actual.Should().Be(expectedData[(int)itemIndex]); - } - } - - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] - public void FindShouldNotFindNonExistingItems(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) - { - _ = testData.Any().Should().BeTrue("we need items on the list that we can look for"); - - // Prepare - using var list = new RecyclableList(testData, itemsCount); - var expectedData = testData.ToList(); - - foreach (var itemIndex in itemIndexes) - { - var expected = expectedData.Find(item => item == -expectedData[(int)itemIndex]); - - // Act - var actual = list.Find(item => item == -expectedData[(int)itemIndex]); - - // Validate - actual.Should().Be(0).And.Be(expected); - } - } - - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))] - public void ForEachShouldGiveItemsInCorrectOrder(string testCase, IEnumerable testData, int itemsCount) - { - // Prepare - using var list = new RecyclableList(testData, itemsCount); - var expectedData = testData.ToList(); - var expected = new List(itemsCount); - expectedData.ForEach(expected.Add); - - // Act - var yieldedItems = new List(itemsCount); - list.ForEach(yieldedItems.Add); - - // Validate - _ = yieldedItems.Should().Equal(testData).And.Equal(expected); - } - - [Theory] - [MemberData(nameof(RecyclableLongListTestData.EmptySourceDataVariants), MemberType = typeof(RecyclableLongListTestData))] - public void ForEachShouldDoNothingWhenEmptyList(string testCase, IEnumerable testData, int itemsCount) - { - // Prepare - using var list = new RecyclableList(testData, itemsCount); - var expectedData = testData.ToList(); - var expected = new List(itemsCount); - expectedData.ForEach(expected.Add); - - // Act - var yieldedItems = new List(itemsCount); - list.ForEach(item => yieldedItems.Add(item)); - - // Validate - _ = yieldedItems.Should().BeEmpty().And.Equal(expected); - } - [Theory] [MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))] public void GetByIndexShouldReturnCorrectItem(string testCase, IEnumerable testData, int itemsCount) @@ -1019,30 +617,6 @@ namespace Recyclable.CollectionsTests } } - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] - public void GetRangeShouldReturnCorrectItems(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) - { - _ = testData.Any().Should().BeTrue("we need items on the list that we can look for"); - - // Prepare - using var list = new RecyclableList(testData, itemsCount); - var expectedData = testData.ToList(); - - foreach (var itemIndex in itemIndexes) - { - int startingIndex = (int)Math.Min(1, itemIndex); - var expectedRangeItems = expectedData.GetRange(startingIndex, (int)itemIndex); - - // Act - using var rangeItems = list.GetRange(startingIndex, (int)itemIndex); - - // Validate - _ = rangeItems.Count.Should().Be(expectedRangeItems.Count); - _ = rangeItems.Should().Equal(expectedRangeItems); - } - } - [Fact] public void IndexOfShouldNotFindAnythingWhenListEmpty() { @@ -1097,122 +671,6 @@ namespace Recyclable.CollectionsTests } } - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] - public void IndexOfShouldReturnCorrectIndexesWhenConstrainedCount(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) - { - // Prepare - using var list = new RecyclableList(testData, itemsCount); - var expectedData = testData.ToList(); - - foreach (var itemIndex in itemIndexes) - { - var expected = expectedData.IndexOf(expectedData[(int)itemIndex], (int)itemIndex, (int)(itemsCount - itemIndex)); - - // Act - var actual = list.IndexOf(expectedData[(int)itemIndex], (int)itemIndex, (int)(itemsCount - itemIndex)); - - // Validate - _ = actual.Should().Be((int)itemIndex).And.Be(expected); - } - } - - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] - public void IndexOfShouldReturnCorrectIndexesWhenConstrainedIndex(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) - { - // Prepare - using var list = new RecyclableList(testData, itemsCount); - var expectedData = testData.ToList(); - - foreach (var itemIndex in itemIndexes) - { - var expected = expectedData.IndexOf(expectedData[(int)itemIndex], (int)itemIndex); - - // Act - var actual = list.IndexOf(expectedData[(int)itemIndex], (int)itemIndex); - - // Validate - _ = actual.Should().Be((int)itemIndex).And.Be(expected); - } - } - - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] - public void LastIndexOfShouldReturnCorrectIndexes(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) - { - // Prepare - using var list = new RecyclableList(testData, itemsCount); - var expectedData = testData.ToList(); - - foreach (var itemIndex in itemIndexes) - { - var expected = expectedData.LastIndexOf(expectedData[(int)itemIndex]); - - // Act - var actual = list.LastIndexOf(expectedData[(int)itemIndex]); - - // Validate - _ = actual.Should().Be((int)itemIndex).And.Be(expected); - } - } - - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] - public void LastIndexOfShouldReturnCorrectIndexesWhenConstrainedCount(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) - { - // Prepare - using var list = new RecyclableList(testData, itemsCount); - var expectedData = testData.ToList(); - - foreach (var itemIndex in itemIndexes) - { - var expected = expectedData.LastIndexOf(expectedData[(int)itemIndex], itemsCount - 1, itemsCount); - - // Act - var actual = list.LastIndexOf(expectedData[(int)itemIndex], itemsCount - 1, itemsCount); - - // Validate - _ = actual.Should().Be((int)itemIndex).And.Be(expected); - } - } - - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] - public void LastIndexOfShouldReturnCorrectIndexesWhenConstrainedIndex(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) - { - // Prepare - using var list = new RecyclableList(testData, itemsCount); - var expectedData = testData.ToList(); - - foreach (var itemIndex in itemIndexes) - { - var expected = expectedData.LastIndexOf(expectedData[(int)itemIndex], itemsCount - 1); - - // Act - var actual = list.LastIndexOf(expectedData[(int)itemIndex], itemsCount - 1); - - // Validate - _ = actual.Should().Be((int)itemIndex).And.Be(expected); - } - } - - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] - public void LastIndexOfShouldThrowArgumentOutOfRangeWhenCountTooBig(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) - { - // Prepare - using var list = new RecyclableList(testData, itemsCount); - var expectedData = testData.ToList(); - - // Act & Validate - foreach (var itemIndex in itemIndexes) - { - _ = Assert.Throws(() => _ = expectedData.LastIndexOf(expectedData[(int)itemIndex], itemsCount - 1, itemsCount + 3).Should().Be((int)itemIndex)); - _ = Assert.Throws(() => _ = list.LastIndexOf(expectedData[(int)itemIndex], itemsCount - 1, itemsCount + 3).Should().Be((int)itemIndex)); - } - } - [Theory] [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] public void InitializeSortClearAddRangeRemoveShouldSucceed(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) @@ -1281,49 +739,6 @@ namespace Recyclable.CollectionsTests } } - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] - public void InsertRangeShouldMoveItems(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) - { - foreach (var itemIndex in itemIndexes) - { - // Prepare - using var list = new RecyclableList(testData.Reverse(), itemsCount); - var expectedItems = testData.Reverse().ToList(); - var item = expectedItems[^1]; - expectedItems.InsertRange((int)itemIndex, testData); - - // Act - list.InsertRange((int)itemIndex, testData); - - // Validate - _ = list[(int)itemIndex].Should().Be(item); - _ = list.Count.Should().Be(itemsCount << 1); - _ = list.Capacity.Should().BeGreaterThanOrEqualTo(itemsCount << 1); - _ = list.Should().Equal(expectedItems); - } - } - - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] - public void RemoveAllShouldRemoveTheCorrectItems(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) - { - // Prepare - using var list = new RecyclableList(testData, itemsCount); - var itemsToRemove = itemIndexes.Select(x => list[(int)x]).ToArray(); - var expectedItems = testData.ToList(); - var expectedResult = expectedItems.RemoveAll(itemsToRemove.Contains); - - // Act - var actualResult = list.RemoveAll(itemsToRemove.Contains); - - // Validate - _ = actualResult.Should().Be(expectedResult); - _ = list.Capacity.Should().BeGreaterThanOrEqualTo(itemsCount); - _ = list.Count.Should().Be(itemsCount - itemsToRemove.Length); - _ = list.Should().Equal(expectedItems); - } - [Theory] [MemberData(nameof(RecyclableLongListTestData.SourceRefDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] public void RemoveAtShouldClearItemWhenReferenceType(string testCase, IEnumerable testData, int itemsCount, in long[] indexesToRemove) @@ -1363,29 +778,6 @@ namespace Recyclable.CollectionsTests } } - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] - public void RemoveRangeShouldRemoveCorrectItems(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) - { - _ = testData.Any().Should().BeTrue("we need items on the list that we can look for"); - - foreach (var itemIndex in itemIndexes) - { - // Prepare - int startingIndex = (int)Math.Min(1, itemIndex); - var expectedData = testData.ToList(); - expectedData.RemoveRange(startingIndex, (int)itemIndex); - - // Act - using var list = new RecyclableList(testData, itemsCount); - list.RemoveRange(startingIndex, (int)itemIndex); - - // Validate - _ = list.Count.Should().Be(expectedData.Count); - _ = list.Should().Equal(expectedData); - } - } - [Theory] [MemberData(nameof(RecyclableLongListTestData.SourceRefDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] public void RemoveShouldClearItemWhenReferenceType(string testCase, IEnumerable testData, int itemsCount, in long[] indexesToRemove) @@ -1430,45 +822,6 @@ namespace Recyclable.CollectionsTests } } - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))] - public void ReverseShouldSwapItemsInCorrectOrder(string testCase, IEnumerable testData, int itemsCount) - { - // Prepare - using var list = new RecyclableList(testData, itemsCount); - var expectedData = testData.ToList(); - expectedData.Reverse(); - - // Act - list.Reverse(); - - // Validate - _ = list.Should().Equal(expectedData); - } - - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] - public void ReverseShouldSwapItemsInCorrectOrderWhenConstrained(string testCase, IEnumerable testData, int itemsCount, long[] itemIndexes) - { - // Prepare - var expectedData = testData.ToArray(); - - foreach (var itemIndex in itemIndexes) - { - // Prepare - using var list = new RecyclableList(testData, itemsCount); - var startingItemIndex = (int)Math.Min(1, itemIndex); - var expectedRangeItems = expectedData.ToList(); - expectedRangeItems.Reverse(startingItemIndex, (int)itemIndex); - - // Act - list.Reverse(startingItemIndex, (int)itemIndex); - - // Validate - _ = list.Should().Equal(expectedRangeItems); - } - } - [Theory] [MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))] public void SetByIndexShouldReturnCorrectItem(string testCase, IEnumerable testData, int itemsCount) @@ -1490,91 +843,6 @@ namespace Recyclable.CollectionsTests } } - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))] - public void SortShouldSortItemsInCorrectOrder(string testCase, IEnumerable testData, int itemsCount) - { - // Prepare - using var list = new RecyclableList(testData.Reverse(), itemsCount); - var expectedData = testData.Reverse().ToList(); - expectedData.Sort(); - - // Act - list.Sort(); - - // Validate - _ = list.Should().Equal(expectedData); - } - - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))] - public void SortShouldSortItemsInCorrectOrderWhenWithComparer(string testCase, IEnumerable testData, int itemsCount) - { - // Prepare - using var list = new RecyclableList(testData.Reverse(), itemsCount); - IComparer comparer = Comparer.Default; - var expectedData = testData.Reverse().ToList(); - expectedData.Sort(comparer); - - // Act - list.Sort(comparer); - - // Validate - _ = list.Should().Equal(expectedData); - } - - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))] - public void SortShouldSortItemsInCorrectOrderWhenWithComparison(string testCase, IEnumerable testData, int itemsCount) - { - // Prepare - using var list = new RecyclableList(testData.Reverse(), itemsCount); - - static int comparison(long x, long y) - { - return (x - y) switch - { - > 0 => 1, - < 0 => -1, - _ => 0, - }; - } - - var expectedData = testData.Reverse().ToList(); - expectedData.Sort(comparison); - - // Act - list.Sort(comparison); - - // Validate - _ = list.Should().Equal(expectedData); - } - - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] - public void SortShouldSortItemsInCorrectOrderWhenConstrained(string testCase, IEnumerable testData, int itemsCount, long[] itemIndexes) - { - // Prepare - IComparer comparer = Comparer.Default; - var expectedData = testData.Reverse().ToArray(); - - foreach (var itemIndex in itemIndexes) - { - // Prepare - using var list = new RecyclableList(testData.Reverse(), itemsCount); - var startingIndex = (int)Math.Min(1, itemIndex); - - var expectedSortedData = expectedData.ToList(); - expectedSortedData.Sort(startingIndex, (int)itemIndex, comparer); - - // Act - list.Sort(startingIndex, (int)itemIndex, comparer); - - // Validate - _ = list.Should().Equal(expectedSortedData); - } - } - [Theory] [MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))] public void ToArrayShouldReturnAllItemsInCorrectOrder(string testCase, IEnumerable testData, int itemsCount) @@ -1591,220 +859,6 @@ namespace Recyclable.CollectionsTests _ = returnedItems.Should().Equal(expectedData); } - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))] - public void TrimExcessShouldDecreaseCapacity(string testCase, IEnumerable testData, int itemsCount) - { - // Prepare - using var list = new RecyclableList(testData, itemsCount); - var expectedCapacity = itemsCount >= RecyclableDefaults.InitialCapacity ? itemsCount : RecyclableDefaults.InitialCapacity; - - // Act - list.TrimExcess(); - - // Validate - _ = list.Capacity.Should().Be(expectedCapacity); - _ = list.Count.Should().Be(itemsCount); - _ = list.Should().Equal(testData); - } - - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))] - public void TrimExcessShouldNotBreakAdd(string testCase, IEnumerable testData, int itemsCount) - { - // Prepare - using var list = new RecyclableList(testData, itemsCount); - var expectedCapacity = (int)BitOperations.RoundUpToPowerOf2((uint)itemsCount + 1); - expectedCapacity = expectedCapacity >= RecyclableDefaults.InitialCapacity ? expectedCapacity : RecyclableDefaults.InitialCapacity; - - // Act - list.TrimExcess(); - list.Add(-1); - - // Validate - _ = list.Capacity.Should().Be(expectedCapacity); - _ = list.Count.Should().Be(itemsCount + 1); - _ = list.Should().Equal(testData.Append(-1)); - } - - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))] - public void TrimExcessShouldNotBreakAddRange(string testCase, IEnumerable testData, int itemsCount) - { - // Prepare - using var list = new RecyclableList(testData, itemsCount); - var expectedCapacity = (int)BitOperations.RoundUpToPowerOf2(checked((uint)itemsCount << 1)); - expectedCapacity = expectedCapacity >= RecyclableDefaults.InitialCapacity ? expectedCapacity : RecyclableDefaults.InitialCapacity; - - // Act - list.TrimExcess(); - list.AddRange(testData); - - // Validate - _ = list.Capacity.Should().BeGreaterThanOrEqualTo(expectedCapacity); - _ = list.Count.Should().Be(itemsCount << 1); - _ = list.Should().Equal(testData.Concat(testData)); - } - - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))] - public void TrimExcessShouldNotBreakClear(string testCase, IEnumerable testData, int itemsCount) - { - // Prepare - using var list = new RecyclableList(testData, itemsCount); - - // Act - list.TrimExcess(); - list.Clear(); - - // Validate - _ = list.Capacity.Should().Be(Math.Max(RecyclableDefaults.InitialCapacity, itemsCount)); - _ = list.Count.Should().Be(0); - _ = list.Should().BeEmpty(); - } - - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] - public void TrimExcessShouldNotBreakInsert(string testCase, IEnumerable testData, int itemsCount, long[] itemIndexes) - { - // Prepare - var expectedCapacity = (int)BitOperations.RoundUpToPowerOf2((uint)itemsCount + 1); - expectedCapacity = expectedCapacity >= RecyclableDefaults.InitialCapacity ? expectedCapacity : RecyclableDefaults.InitialCapacity; - var expectedData = testData.ToArray(); - - foreach (var itemIndex in itemIndexes) - { - using var list = new RecyclableList(testData, itemsCount); - var expectedItemsAfterInsert = expectedData.ToList(); - expectedItemsAfterInsert.Insert((int)itemIndex, -3); - - // Act - list.TrimExcess(); - list.Insert((int)itemIndex, -3); - - // Validate - _ = list.Capacity.Should().BeGreaterThanOrEqualTo(expectedCapacity); - _ = list.Count.Should().Be(expectedItemsAfterInsert.Count); - _ = list.Should().Equal(expectedItemsAfterInsert); - } - } - - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] - public void TrimExcessShouldNotBreakRemove(string testCase, IEnumerable testData, int itemsCount, long[] itemIndexes) - { - // Prepare - var expectedData = testData.ToArray(); - - foreach (var itemIndex in itemIndexes) - { - using var list = new RecyclableList(testData, itemsCount); - var expectedItemsAfterInsert = expectedData.ToList(); - expectedItemsAfterInsert.RemoveAt((int)itemIndex); - - // Act - list.TrimExcess(); - list.RemoveAt((int)itemIndex); - - // Validate - _ = list.Capacity.Should().BeGreaterThanOrEqualTo(itemsCount); - _ = list.Count.Should().Be(expectedItemsAfterInsert.Count); - _ = list.Should().Equal(expectedItemsAfterInsert); - } - } - - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] - public void TrimExcessShouldNotBreakIndexOf(string testCase, IEnumerable testData, int itemsCount, long[] itemIndexes) - { - // Prepare - var expectedData = testData.ToArray(); - - foreach (var itemIndex in itemIndexes) - { - using var list = new RecyclableList(testData, itemsCount); - - // Act - list.TrimExcess(); - var actual = list.IndexOf(expectedData[(int)itemIndex]); - - // Validate - _ = actual.Should().Be((int)itemIndex); - } - } - - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))] - public void TrimmedArraysShouldNotBePooled(string testCase, IEnumerable testData, int itemsCount) - { - // Prepare - using var list = new RecyclableList(testData, itemsCount); - - // Act - list.TrimExcess(); - var trimmedMemoryBlock = list._memoryBlock; - - list.Dispose(); - - // Validate - _ = list.Capacity.Should().Be(0); - _ = list.Count.Should().Be(0); - _ = list.Should().BeEmpty(); - - if (itemsCount >= RecyclableDefaults.MinPooledArrayLength) - { - var newMemoryBlock = RecyclableArrayPool.RentShared(itemsCount); - if (BitOperations.IsPow2(itemsCount)) - { - _ = newMemoryBlock.Should().BeSameAs(trimmedMemoryBlock); - } - else - { - _ = newMemoryBlock.Should().NotBeSameAs(trimmedMemoryBlock); - } - } - } - - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] - public void TrueForAllShouldBeFalseWhenNoMatch(string testCase, IEnumerable testData, int itemsCount, long[] itemIndexes) - { - // Prepare - var expectedData = testData.ToList(); - - foreach (var itemIndex in itemIndexes) - { - using RecyclableList list = new(testData, itemsCount); - Predicate condition = item => item == itemIndex; - var expected = expectedData.TrueForAll(condition); - - // Act - var actual = list.TrueForAll(condition); - - // Validate - _ = actual.Should().Be(expected).And.BeFalse(); - } - } - - [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] - public void TrueForAllShouldBeTrueWhenMatched(string testCase, IEnumerable testData, int itemsCount, long[] itemIndexes) - { - // Prepare - using RecyclableList list = new(testData, itemsCount); - int index = 0; - Predicate condition = item => item == ++index; - var expected = testData.ToList().TrueForAll(condition); - - index = 0; - - // Act - var actual = list.TrueForAll(condition); - - // Validate - _ = actual.Should().Be(expected).And.BeTrue(); - } - [Theory] [MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))] public void VersionedEnumerateShouldRaiseExceptionWhenCollectionIsModified(string testCase, IEnumerable testData, int itemsCount) diff --git a/Recyclable.CollectionsTests/RecyclableLongListTestData.cs b/Recyclable.CollectionsTests/RecyclableLongListTestData.cs deleted file mode 100644 index a9f5a30..0000000 --- a/Recyclable.CollectionsTests/RecyclableLongListTestData.cs +++ /dev/null @@ -1,282 +0,0 @@ -using MoreLinq; -using Open.Numeric.Primes; -using Recyclable.Collections; -using System.Numerics; - -namespace Recyclable.CollectionsTests -{ - public static class RecyclableLongListTestData - { - - private static readonly object[] _sourceRefData = Enumerable.Range(1, 100).Cast().ToArray(); - public static object[] SourceRefData => _sourceRefData; - - public static IEnumerable CreateTestData(long itemsCount) - { - for (long index = 1; index <= itemsCount; index++) - { - yield return index; - } - } - - public static IEnumerable CreateRefTestData(long itemsCount) - { - for (long index = 1; index <= itemsCount; index++) - { - yield return index; - } - } - - public static readonly IEnumerable 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 ItemsCountTestCases = ItemsCountVariants.Select(x => new object[] { (int)x }); - - public static readonly IEnumerable 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 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 TargetDataVariants => GetTargetDataVariants(); - - private static IEnumerable CombineSourceDataWithBlockSize(IEnumerable 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 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[{itemsCount}]", testData, itemsCount }; - yield return new object[] { $"IEnumerable[{itemsCount}]", testData, itemsCount }; - yield return new object[] { $"IEnumerable[{itemsCount}] without non-enumerated count", new EnumerableWithoutCount(testData), itemsCount }; - yield return new object[] { $"IList[{itemsCount}]", new CustomIList(testData), itemsCount }; - yield return new object[] { $"IReadOnlyList[{itemsCount}])", testData, itemsCount }; - yield return new object[] { $"List[{itemsCount}]", testData.ToList(), itemsCount }; - yield return new object[] { $"ReadOnlySpan[{itemsCount}]", testData, itemsCount }; - yield return new object[] { $"RecyclableList[{itemsCount}]", testData.ToRecyclableList(), itemsCount }; - - foreach (var sourceBlockSize in BlockSizeVariants) - { - if (!IsValidBlockSize(itemsCount, sourceBlockSize)) - { - continue; - } - - yield return new object[] - { - $"RecyclableLongList[itemsCount: {itemsCount}, minBlockSize: {sourceBlockSize}]", - testData.ToRecyclableLongList(sourceBlockSize), - itemsCount - }; - } - - yield return new object[] { $"Span[{itemsCount}]", testData, itemsCount }; - yield return new object[] { $"T[{itemsCount}]", testData, itemsCount }; - break; - - case true: - IEnumerable 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(itemsCount: {itemsCount}", testRefData, itemsCount }; - yield return new object[] { $"IEnumerable(itemsCount: {itemsCount})", testRefData, itemsCount }; - yield return new object[] { $"IEnumerable(itemsCount: {itemsCount}) without non-enumerated count", new EnumerableWithoutCount(testRefData), itemsCount }; - yield return new object[] { $"IList(itemsCount: {itemsCount})", new CustomIList(testRefData), itemsCount }; - yield return new object[] { $"IReadOnlyList(itemsCount: {itemsCount})", testRefData, itemsCount }; - yield return new object[] { $"List(itemsCount: {itemsCount}", testRefData.ToList(), itemsCount }; - yield return new object[] { $"ReadOnlySpan[{itemsCount}]", testRefData, itemsCount }; - yield return new object[] { $"RecyclableList(itemsCount: {itemsCount})", testRefData.ToRecyclableList(), itemsCount }; - - foreach (var sourceBlockSize in BlockSizeVariants) - { - if (!IsValidBlockSize(itemsCount, sourceBlockSize)) - { - continue; - } - - yield return new object[] - { - $"RecyclableLongList(itemsCount: {itemsCount}, minBlockSize: {sourceBlockSize})", - testRefData.ToRecyclableLongList(sourceBlockSize), - itemsCount - }; - } - - yield return new object[] { $"Span[{itemsCount}]", testRefData, itemsCount }; - yield return new object[] { $"T[{itemsCount}]", testRefData, itemsCount }; - break; - } - } - - private static IEnumerable CreateSourceDataVariants(bool refType) - { - foreach (var itemsCount in ItemsCountVariants) - { - foreach (var variant in CreateSourceDataVariants(itemsCount, refType)) - { - yield return variant; - } - } - } - - public static IEnumerable EmptySourceDataVariants => CreateSourceDataVariants(0, false); - public static IEnumerable SourceDataVariants => CreateSourceDataVariants(false); - public static IEnumerable 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 SourceRefDataWithItemIndexVariants - { - get - { - IEnumerable 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 SourceDataWithBlockSizeVariants => CombineSourceDataWithBlockSize(SourceDataVariants); - public static IEnumerable SourceRefDataVariants => CreateSourceDataVariants(true); - public static IEnumerable SourceRefDataWithBlockSizeVariants { get; } = CombineSourceDataWithBlockSize(SourceRefDataVariants); - - private static IEnumerable _initialItemIndexVariants => new long[] { 0, 1, 2, 3, 4, 5 }; - private static IEnumerable CreateItemIndexVariants(long itemsCount, int blockSize) - { - IEnumerable 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 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 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 CombineSourceRefDataWithBlockSizeWithItemIndex(bool refType) - { - IEnumerable 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 SourceDataWithBlockSizeWithItemIndexVariants { get; } = CombineSourceRefDataWithBlockSizeWithItemIndex(false); - public static IEnumerable SourceRefDataWithBlockSizeWithItemIndexVariants { get; } = CombineSourceRefDataWithBlockSizeWithItemIndex(true); - } -} \ No newline at end of file diff --git a/Recyclable.CollectionsTests/RecyclableLongListTests.cs b/Recyclable.CollectionsTests/RecyclableLongListTests.cs index 9c74a9a..5f37dd1 100644 --- a/Recyclable.CollectionsTests/RecyclableLongListTests.cs +++ b/Recyclable.CollectionsTests/RecyclableLongListTests.cs @@ -1,5 +1,6 @@ using FluentAssertions; using Recyclable.Collections; +using Recyclable.Collections.TestData; using Recyclable.Collections.Linq; using System.Collections; using System.Numerics; diff --git a/logo.png b/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..da8146096e79f5b9cff6fffaf17b827d57f37afd GIT binary patch literal 14559 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