Cleanup of no longer needed classes. ParallelSynchronizationContext/-Pool renamed to IndexOfSynchronizationContext/-Pool.

This commit is contained in:
mlemanczyk committed 2023-05-21 16:10:21 +02:00
1 parent 9ece531129
commit 24c2491df0
9 files changed
+80 -255

No files matched your search

@@ -1,10 +1,11 @@
using BenchmarkDotNet.Attributes;
using Microsoft.Extensions.ObjectPool;
using MoreLinq;
using System.Runtime.CompilerServices;
namespace Recyclable.Collections.Benchmarks.POC
{
public enum WhenParallelSearchBenchmarkType
public enum WhenParallelSearchBenchmarkType
{
IndexOfSequentially,
IndexOfParallel,
@@ -13,6 +14,62 @@ namespace Recyclable.Collections.Benchmarks.POC
[MemoryDiagnoser]
public class WhenParallelSearchBenchmarks : PocBenchmarkBase<WhenParallelSearchBenchmarkType>
{
#region ItemRange V2
private sealed class ItemRangeV2
{
public int BlockIndex;
public long ItemsToSearchCount;
internal bool _returned;
public ItemRangeV2()
{
}
public ItemRangeV2(int blockIndex, long itemsToSearchCount)
{
BlockIndex = blockIndex;
ItemsToSearchCount = itemsToSearchCount;
}
public void Dispose()
{
if (!_returned)
{
_returned = true;
ItemRangePoolV2.Shared.Return(this);
}
}
}
#endregion
#region ItemRangePoolV2
private static class ItemRangePoolV2
{
private static readonly SpinLock _updateLock = new(false);
public static readonly ObjectPool<ItemRangeV2> Shared = new DefaultObjectPool<ItemRangeV2>(new DefaultPooledObjectPolicy<ItemRangeV2>());
public static ItemRangeV2 Create(int blockIndex, long itemsToSearchCount)
{
bool lockTaken = false;
_updateLock.Enter(ref lockTaken);
var itemRange = Shared.Get();
if (lockTaken)
{
_updateLock.Exit(false);
}
itemRange._returned = false;
itemRange.BlockIndex = blockIndex;
itemRange.ItemsToSearchCount = itemsToSearchCount;
return itemRange;
}
}
#endregion
//[Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 32)]
//public int NumberOfThreads { get; set; } = 3;
@@ -66,7 +123,7 @@ namespace Recyclable.Collections.Benchmarks.POC
}
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
private static long DoLongIndexOfParallel(RecyclableList<long> list, in long itemToFind, ItemRange searchInfo, ManualResetEventSlim itemFoundSignal)
private static long DoLongIndexOfParallel(RecyclableList<long> list, in long itemToFind, ItemRangeV2 searchInfo, ManualResetEventSlim itemFoundSignal)
{
int index;
int blockSize = list.BlockSize;
@@ -248,13 +305,13 @@ namespace Recyclable.Collections.Benchmarks.POC
}
protected override Action? GetTestMethod(WhenParallelSearchBenchmarkType benchmarkType) => BenchmarkType switch
{
WhenParallelSearchBenchmarkType.IndexOfSequentially => IndexOfSequentially,
WhenParallelSearchBenchmarkType.IndexOfParallel => IndexOfParallel,
_ => throw CreateUnknownBenchmarkTypeException(benchmarkType),
};
{
WhenParallelSearchBenchmarkType.IndexOfSequentially => IndexOfSequentially,
WhenParallelSearchBenchmarkType.IndexOfParallel => IndexOfParallel,
_ => throw CreateUnknownBenchmarkTypeException(benchmarkType),
};
public override void Cleanup()
public override void Cleanup()
{
_testData = default;
base.Cleanup();
-30
View File
@@ -1,30 +0,0 @@
using Recyclable.Collections.Pools;
namespace Recyclable.Collections
{
public sealed class ItemRange
{
public int BlockIndex;
public long ItemsToSearchCount;
internal bool _returned;
public ItemRange()
{
}
public ItemRange(int blockIndex, long itemsToSearchCount)
{
BlockIndex = blockIndex;
ItemsToSearchCount = itemsToSearchCount;
}
public void Dispose()
{
if (!_returned)
{
_returned = true;
ItemRangePool.Shared.Return(this);
}
}
}
}
@@ -1,30 +0,0 @@
using System.Runtime.CompilerServices;
using Recyclable.Collections.Parallel;
namespace Recyclable.Collections
{
public static class ItemRangesIterator
{
[MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.NoInlining)]
public static void Iterate<TList, T>(in ParallelSynchronizationContext context, in SearchConfiguration<TList, T> search, Func<ParallelSynchronizationContext, SearchConfiguration<TList, T>, ItemRange, bool> action)
{
ItemRange itemRange;
int blockIndex = search.StartingBlockIndex;
long itemsCount = search.ItemsCount;
while (itemsCount > search.BlockSize)
{
itemRange = new(blockIndex, search.BlockSize);
if (!action(context, search, itemRange))
{
break;
}
itemsCount -= search.BlockSize;
blockIndex++;
}
itemRange = new(blockIndex, itemsCount);
_ = action(context, search, itemRange);
}
}
}
@@ -1,6 +1,6 @@
namespace Recyclable.Collections.Parallel
{
public sealed class ParallelSynchronizationContext : IDisposable
public sealed class IndexOfSynchronizationContext : IDisposable
{
internal bool _isItemFound;
@@ -9,12 +9,12 @@ namespace Recyclable.Collections.Parallel
public Exception? Exception;
internal bool _returned;
public ParallelSynchronizationContext()
public IndexOfSynchronizationContext()
{
AllDoneSignal = new(0);
}
public ParallelSynchronizationContext(int participantCount)
public IndexOfSynchronizationContext(int participantCount)
{
AllDoneSignal = new(participantCount);
}
@@ -31,7 +31,7 @@ namespace Recyclable.Collections.Parallel
if (!_returned)
{
_returned = true;
ParallelSynchronizationContextPool.Shared.Return(this);
IndexOfSynchronizationContextPool.Shared.Return(this);
}
else
{
@@ -2,12 +2,12 @@ using Microsoft.Extensions.ObjectPool;
namespace Recyclable.Collections.Parallel
{
public static class ParallelSynchronizationContextPool
public static class IndexOfSynchronizationContextPool
{
private static readonly SpinLock _updateLock = new(false);
public static readonly ObjectPool<ParallelSynchronizationContext> Shared = new DefaultObjectPool<ParallelSynchronizationContext>(new DefaultPooledObjectPolicy<ParallelSynchronizationContext>());
public static readonly ObjectPool<IndexOfSynchronizationContext> Shared = new DefaultObjectPool<IndexOfSynchronizationContext>(new DefaultPooledObjectPolicy<IndexOfSynchronizationContext>());
public static ParallelSynchronizationContext GetWithOneParticipant()
public static IndexOfSynchronizationContext GetWithOneParticipant()
{
bool lockTaken = false;
_updateLock.Enter(ref lockTaken);
@@ -1,26 +0,0 @@
using Microsoft.Extensions.ObjectPool;
namespace Recyclable.Collections.Pools
{
public static class ItemRangePool
{
private static readonly SpinLock _updateLock = new(false);
public static readonly ObjectPool<ItemRange> Shared = new DefaultObjectPool<ItemRange>(new DefaultPooledObjectPolicy<ItemRange>());
public static ItemRange Create(int blockIndex, long itemsToSearchCount)
{
bool lockTaken = false;
_updateLock.Enter(ref lockTaken);
var itemRange = Shared.Get();
if (lockTaken)
{
_updateLock.Exit(false);
}
itemRange._returned = false;
itemRange.BlockIndex = blockIndex;
itemRange.ItemsToSearchCount = itemsToSearchCount;
return itemRange;
}
}
}
@@ -5,12 +5,12 @@ namespace Recyclable.Collections
{
public partial class RecyclableList<T>
{
public static class RecyclableListIndexOfHelpers
public static class IndexOfHelpers
{
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
// [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.NoOptimization)]
private static void ScheduleIndexOfTask(ParallelSynchronizationContext context, RecyclableList<T> list, int blockIndex, T itemToFind)
private static void ScheduleIndexOfTask(IndexOfSynchronizationContext context, RecyclableList<T> list, int blockIndex, T itemToFind)
{
_ = context.AllDoneSignal.AddParticipant();
// & WAS SLOWER
@@ -123,7 +123,7 @@ namespace Recyclable.Collections
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
// [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.NoOptimization)]
private static void ScheduleIndexOfTaskSingle(ParallelSynchronizationContext context, RecyclableList<T> list, int blockIndex, T itemToFind)
private static void ScheduleIndexOfTaskSingle(IndexOfSynchronizationContext context, RecyclableList<T> list, int blockIndex, T itemToFind)
{
_ = context.AllDoneSignal.AddParticipant();
// & WAS SLOWER
@@ -172,7 +172,7 @@ namespace Recyclable.Collections
//}
//using var context = new ParallelSynchronizationContext(1);
ParallelSynchronizationContext context = ParallelSynchronizationContextPool.GetWithOneParticipant();
IndexOfSynchronizationContext context = IndexOfSynchronizationContextPool.GetWithOneParticipant();
// (long)(_longCount * 0.329) => most efficient step, based on benchmarks
//Iterate(this, context, item);
+4 -4
View File
@@ -857,7 +857,7 @@ namespace Recyclable.Collections
}
else if (_longCount < RecyclableDefaults.MinItemsCountForParallelization)
{
return (int)RecyclableListIndexOfHelpers.IndexOfSequential(this, item);
return (int)IndexOfHelpers.IndexOfSequential(this, item);
}
else
{
@@ -866,7 +866,7 @@ namespace Recyclable.Collections
if (_longCount > _blockSize)
{
itemIndex = Array.IndexOf(_memoryBlocks[1], item, 0, (int)Math.Min(_blockSize, _longCount - _blockSize));
return itemIndex >= 0 ? _blockSize + itemIndex : (int)RecyclableListIndexOfHelpers.IndexOfParallel(this, item);
return itemIndex >= 0 ? _blockSize + itemIndex : (int)IndexOfHelpers.IndexOfParallel(this, item);
}
else
{
@@ -896,7 +896,7 @@ namespace Recyclable.Collections
}
else if (_longCount < RecyclableDefaults.MinItemsCountForParallelization)
{
return RecyclableListIndexOfHelpers.IndexOfSequential(this, item);
return IndexOfHelpers.IndexOfSequential(this, item);
}
else
{
@@ -905,7 +905,7 @@ namespace Recyclable.Collections
if (_longCount > _blockSize)
{
itemIndex = Array.IndexOf(_memoryBlocks[1], item, 0, (int)Math.Min(_blockSize, _longCount - _blockSize));
return itemIndex >= 0 ? _blockSize + itemIndex : RecyclableListIndexOfHelpers.IndexOfParallel(this, item);
return itemIndex >= 0 ? _blockSize + itemIndex : IndexOfHelpers.IndexOfParallel(this, item);
}
else
{
@@ -1,146 +0,0 @@
using FluentAssertions;
using Recyclable.Collections;
using Recyclable.Collections.Parallel;
using System.Numerics;
namespace Recyclable.CollectionsTests
{
public class ItemRangesIteratorTests
{
[Theory]
[MemberData(nameof(TestCases))]
public void IterateShouldYieldAllItems(int startingBlockIndex, int blockSize, long itemsCount, int step, IEnumerable<(int BlockIndex, long ItemsCount)> expected)
{
// Prepare
var mockList = new RecyclableList<long>();
byte blockSizePow2BitShift = (byte)(31 - BitOperations.LeadingZeroCount((uint)blockSize));
var synchronizationContext = new ParallelSynchronizationContext(1);
var search = new SearchConfiguration<RecyclableList<long>, long>()
{
List = mockList,
ItemToFind = 0,
BlockSizeMinus1 = blockSize - 1,
BlockSizePow2BitShift = blockSizePow2BitShift,
ItemsCount = itemsCount,
BlockSize = step,
};
var actualItemRanges = new List<(int BlockIndex, long ItemsCount)>();
// Act
ItemRangesIterator.Iterate(synchronizationContext, search, (context, search, itemRange) =>
{
actualItemRanges.Add((itemRange.BlockIndex, itemRange.ItemsToSearchCount));
return true;
});
// Validate
_ = actualItemRanges.Should().HaveCount(expected.Count()).And.ContainInConsecutiveOrder(expected);
}
public static IEnumerable<object[]> TestCases => new[]
{
new object[]
{
0, 128, 333, (long)(333 * 0.329), new(int BlockIndex, long ItemsCount)[]
{
(0, 109),
(0, 109),
(1, 109),
(2, 6)
}
},
new object[]
{
0, 2, 10, 2, new (int BlockIndex, long ItemsCount)[]
{
(0, 2),
(1, 2),
(2, 2),
(3, 2),
(4, 2),
}
},
new object[]
{
0, 2, 10, 3, new (int BlockIndex, long ItemsCount)[]
{
(0, 3),
(1, 3),
(3, 3),
(4, 1),
}
},
new object[]
{
0, 1, 10, 3, new (int BlockIndex, long ItemsCount)[]
{
(0, 3),
(3, 3),
(6, 3),
(9, 1),
}
},
new object[]
{
0, 2, 10, 4, new (int BlockIndex, long ItemsCount)[]
{
(0, 4),
(2, 4),
(4, 2),
}
},
new object[]
{
0, 1, 10, 2, new (int BlockIndex, long ItemsCount)[]
{
(0, 2),
(2, 2),
(4, 2),
(6, 2),
(8, 2),
}
},
new object[]
{
0, 2, 10, 1, new (int BlockIndex, long ItemsCount)[]
{
(0, 1),
(0, 1),
(1, 1),
(1, 1),
(2, 1),
(2, 1),
(3, 1),
(3, 1),
(4, 1),
(4, 1),
}
},
new object[]
{
0, 1, 10, 1, new (int BlockIndex, long ItemsCount)[]
{
(0, 1),
(1, 1),
(2, 1),
(3, 1),
(4, 1),
(5, 1),
(6, 1),
(7, 1),
(8, 1),
(9, 1),
}
},
};
}
}