From 73d3e32107f4e259da45303a062da277e184d2aa Mon Sep 17 00:00:00 2001 From: mlemanczyk Date: Wed, 3 May 2023 15:19:56 +0200 Subject: [PATCH] Benchmark performance improvements - pattern for all test cases prepared. --- .../POC/PocBenchmarkBase.cs | 4 +- ...clableListPoc.Benchmarks.EnsureCapacity.cs | 8 -- .../RecyclableListPoc.Benchmarks.IndexOf.cs | 7 +- .../POC/RecyclableListPoc.Benchmarks.cs | 86 +++++++++++++++---- 4 files changed, 70 insertions(+), 35 deletions(-) diff --git a/Recyclable.Collections.Benchmarks/POC/PocBenchmarkBase.cs b/Recyclable.Collections.Benchmarks/POC/PocBenchmarkBase.cs index 689c121..254f92d 100644 --- a/Recyclable.Collections.Benchmarks/POC/PocBenchmarkBase.cs +++ b/Recyclable.Collections.Benchmarks/POC/PocBenchmarkBase.cs @@ -27,8 +27,8 @@ namespace Recyclable.Collections.Benchmarks.POC public int BlockSize => TestObjectCount switch { 0 => 1, - > 0 and <= 10 => (int)TestObjectCount, - _ => TestObjectCount / Divider > 0 ? checked((int)(TestObjectCount / Divider)) : checked((int)TestObjectCount) + > 0 and <= 10 => TestObjectCount, + _ => TestObjectCount / Divider > 0 ? TestObjectCount / Divider : TestObjectCount }; public byte BlockSizePow2BitShift => checked((byte)(31 - BitOperations.LeadingZeroCount((uint)BlockSize))); diff --git a/Recyclable.Collections.Benchmarks/POC/RecyclableListPoc.Benchmarks.EnsureCapacity.cs b/Recyclable.Collections.Benchmarks/POC/RecyclableListPoc.Benchmarks.EnsureCapacity.cs index c8ff64a..6a2b9da 100644 --- a/Recyclable.Collections.Benchmarks/POC/RecyclableListPoc.Benchmarks.EnsureCapacity.cs +++ b/Recyclable.Collections.Benchmarks/POC/RecyclableListPoc.Benchmarks.EnsureCapacity.cs @@ -2808,56 +2808,48 @@ namespace Recyclable.Collections.Benchmarks.POC public partial class RecyclableListPocBenchmarks { - [Benchmark(Baseline = false)] public void RecyclableList_EnsureCapacityV1_ByPowOf2() { using var list = new RecyclableListV1(minBlockSize: BlockSize, expectedItemsCount: TestObjectCount); DoNothing(_ensureCapacityV1Func.Invoke(list, new object[] { TestObjectCount })); } - [Benchmark(Baseline = true)] public void RecyclableList_EnsureCapacityV2_ByPowOf2() { using var list = new RecyclableListV2(minBlockSize: BlockSize, expectedItemsCount: TestObjectCount); DoNothing(_ensureCapacityV2Func.Invoke(null, new object[] { list, TestObjectCount })); } - [Benchmark(Baseline = true)] public void RecyclableList_EnsureCapacityV3_ByPowOf2() { using var list = new RecyclableListV3(minBlockSize: BlockSize, expectedItemsCount: TestObjectCount); DoNothing(_ensureCapacityV3Func.Invoke(null, new object[] { list, TestObjectCount })); } - [Benchmark(Baseline = false)] public void RecyclableList_EnsureCapacity_ByPowOf2() { using var list = new RecyclableList(minBlockSize: BlockSize, expectedItemsCount: TestObjectCount); DoNothing(_ensureCapacityNewFunc.Invoke(null, new object[] { list, TestObjectCount })); } - [Benchmark(Baseline = false)] public void RecyclableList_EnsureCapacityV1_ByBlockSize() { using var list = new RecyclableListV1(); DoNothing(_ensureCapacityV1Func.Invoke(list, new object[] { TestObjectCount })); } - [Benchmark(Baseline = false)] public void RecyclableList_EnsureCapacityV2_ByBlockSize() { using var list = new RecyclableListV2(); DoNothing(_ensureCapacityV2Func.Invoke(null, new object[] { list, TestObjectCount })); } - [Benchmark(Baseline = false)] public void RecyclableList_EnsureCapacityV3_ByBlockSize() { using var list = new RecyclableListV3(); DoNothing(_ensureCapacityV3Func.Invoke(null, new object[] { list, TestObjectCount })); } - [Benchmark(Baseline = false)] public void RecyclableList_EnsureCapacity_ByBlockSize() { using var list = new RecyclableList(); diff --git a/Recyclable.Collections.Benchmarks/POC/RecyclableListPoc.Benchmarks.IndexOf.cs b/Recyclable.Collections.Benchmarks/POC/RecyclableListPoc.Benchmarks.IndexOf.cs index 4a646f3..3e34a5c 100644 --- a/Recyclable.Collections.Benchmarks/POC/RecyclableListPoc.Benchmarks.IndexOf.cs +++ b/Recyclable.Collections.Benchmarks/POC/RecyclableListPoc.Benchmarks.IndexOf.cs @@ -4654,11 +4654,11 @@ namespace Recyclable.Collections.Benchmarks.POC } } } + #endregion public partial class RecyclableListPocBenchmarks { - // [Benchmark(Baseline = true)] public void RecyclableList_IndexOfV1() { var data = TestObjects; @@ -4670,7 +4670,6 @@ namespace Recyclable.Collections.Benchmarks.POC } } - // [Benchmark(Baseline = true)] public void PooledList_IndexOf() { var data = TestObjects; @@ -4682,7 +4681,6 @@ namespace Recyclable.Collections.Benchmarks.POC } } - // [Benchmark(Baseline = false)] public void RecyclableList_IndexOfV2() { var data = TestObjects; @@ -4694,7 +4692,6 @@ namespace Recyclable.Collections.Benchmarks.POC } } - // [Benchmark(Baseline = false)] public void RecyclableList_IndexOfV3() { var data = TestObjects; @@ -4706,7 +4703,6 @@ namespace Recyclable.Collections.Benchmarks.POC } } - // [Benchmark(Baseline = true)] public void RecyclableList_IndexOfV4() { var data = TestObjects; @@ -4718,7 +4714,6 @@ namespace Recyclable.Collections.Benchmarks.POC } } - [Benchmark(Baseline = false)] public void RecyclableList_IndexOf() { var data = TestObjects; diff --git a/Recyclable.Collections.Benchmarks/POC/RecyclableListPoc.Benchmarks.cs b/Recyclable.Collections.Benchmarks/POC/RecyclableListPoc.Benchmarks.cs index 69e381e..0387c74 100644 --- a/Recyclable.Collections.Benchmarks/POC/RecyclableListPoc.Benchmarks.cs +++ b/Recyclable.Collections.Benchmarks/POC/RecyclableListPoc.Benchmarks.cs @@ -1,14 +1,35 @@ using System.Reflection; -using System.Runtime.CompilerServices; using BenchmarkDotNet.Attributes; using Collections.Pooled; using Recyclable.Collections.Benchmarks.Core; namespace Recyclable.Collections.Benchmarks.POC { + public enum RecyclableListPocBenchmarkType + { + IndexOfV1, + IndexOfV2, + IndexOfV3, + IndexOfV4, + IndexOf_PooledList, + IndexOf, + EnsureCapacity_ByPowOf2, + EnsureCapacityV1_ByPowOf2, + EnsureCapacityV2_ByPowOf2, + EnsureCapacityV3_ByPowOf2, + } + public partial class RecyclableListPocBenchmarks : PocBenchmarkBase { - private long[]? _testArray; + [Params(BenchmarkType.Array, BenchmarkType.List, BenchmarkType.PooledList, BenchmarkType.RecyclableArrayList, BenchmarkType.RecyclableList)] + // [Params(RecyclableListPocBenchmarkType.IndexOf)] + public RecyclableListPocBenchmarkType _benchmarkType; + private Action? _testMethod; + + [Benchmark] + public void RunWhen() => _testMethod!.Invoke(); + + private long[]? _testArray; public long[] TestObjects => _testArray ?? throw new NullReferenceException("Something is wrong and test objects are null"); private RecyclableList? _testRecyclableList; public RecyclableList TestObjectsAsRecyclableList => _testRecyclableList ?? throw new NullReferenceException($"Something is wrong and {nameof(RecyclableList)} is null"); @@ -64,25 +85,52 @@ namespace Recyclable.Collections.Benchmarks.POC [GlobalSetup] public void Setup() { + Console.WriteLine($"Setting up exptected results data"); _testArray = DataGenerator.EnumerateTestObjects(TestObjectCount); - _testRecyclableList = new(TestObjects, BlockSize, expectedItemsCount: TestObjectCount); - _testRecyclableListIndexOfV1 = new(TestObjects, BlockSize, expectedItemsCount: TestObjectCount); - _testRecyclableListIndexOfV2 = new(TestObjects, BlockSize, expectedItemsCount: TestObjectCount); - _testRecyclableListIndexOfV3 = new(TestObjects, BlockSize, expectedItemsCount: TestObjectCount); - _testRecyclableListIndexOfV4 = new(TestObjects, BlockSize, expectedItemsCount: TestObjectCount); - _testPooledList = new PooledList(TestObjects, ClearMode.Auto); + Console.WriteLine($"Setting up test case for benchmark {{{_benchmarkType}}}"); + switch (_benchmarkType) + { + case RecyclableListPocBenchmarkType.IndexOfV1: + _testRecyclableListIndexOfV1 = new(TestObjects, BlockSize, expectedItemsCount: TestObjectCount); + _testMethod = () => RecyclableList_IndexOfV1(); + break; + case RecyclableListPocBenchmarkType.IndexOfV2: + _testRecyclableListIndexOfV2 = new(TestObjects, BlockSize, expectedItemsCount: TestObjectCount); + _testMethod = () => RecyclableList_IndexOfV2(); + break; + case RecyclableListPocBenchmarkType.IndexOfV3: + _testRecyclableListIndexOfV3 = new(TestObjects, BlockSize, expectedItemsCount: TestObjectCount); + _testMethod = () => RecyclableList_IndexOfV3(); + break; + case RecyclableListPocBenchmarkType.IndexOfV4: + _testRecyclableListIndexOfV4 = new(TestObjects, BlockSize, expectedItemsCount: TestObjectCount); + _testMethod = () => RecyclableList_IndexOfV4(); + break; + case RecyclableListPocBenchmarkType.IndexOf_PooledList: + _testPooledList = new PooledList(TestObjects, ClearMode.Auto); + _testMethod = () => PooledList_IndexOf(); + break; + case RecyclableListPocBenchmarkType.IndexOf: + _testRecyclableList = new(TestObjects, BlockSize, expectedItemsCount: TestObjectCount); + _testMethod = () => RecyclableList_IndexOf(); + break; + case RecyclableListPocBenchmarkType.EnsureCapacity_ByPowOf2: + _testMethod = () => RecyclableList_EnsureCapacity_ByPowOf2(); + break; + case RecyclableListPocBenchmarkType.EnsureCapacityV1_ByPowOf2: + _testMethod = () => RecyclableList_EnsureCapacityV1_ByPowOf2(); + break; + case RecyclableListPocBenchmarkType.EnsureCapacityV2_ByPowOf2: + _testMethod = () => RecyclableList_EnsureCapacityV2_ByPowOf2(); + break; + case RecyclableListPocBenchmarkType.EnsureCapacityV3_ByPowOf2: + _testMethod = () => RecyclableList_EnsureCapacityV3_ByPowOf2(); + break; + default: + throw new InvalidOperationException($"Unknown benchmark type {{{_benchmarkType}}}"); + } - // Warm up memory pools for fair comparison with 1st run - RecyclableList_EnsureCapacity_ByPowOf2(); - RecyclableList_EnsureCapacityV1_ByPowOf2(); - RecyclableList_EnsureCapacityV2_ByPowOf2(); - RecyclableList_EnsureCapacityV3_ByPowOf2(); - RecyclableList_IndexOf(); - RecyclableList_IndexOfV1(); - RecyclableList_IndexOfV2(); - RecyclableList_IndexOfV3(); - RecyclableList_IndexOfV4(); - PooledList_IndexOf(); + Console.WriteLine("Data prepared"); } [GlobalCleanup]