From 96968d5452fe4ee4d3207f977f534a976c9f3158 Mon Sep 17 00:00:00 2001 From: mlemanczyk Date: Sun, 3 Sep 2023 14:42:18 +0200 Subject: [PATCH] Small cleanup --- .../Recyclable.Collections.csproj | 1 - Recyclable.Collections/RecyclableDefaults.cs | 1 - .../RecyclableList.Helpers.cs | 13 +++-- Recyclable.Collections/RecyclableList.cs | 30 +++++----- .../RecyclableLongList.Enumerator.cs | 4 +- .../RecyclableLongList.Helpers.cs | 2 +- .../RecyclableLongList.VersionedEnumerator.cs | 4 +- Recyclable.Collections/RecyclableLongList.cs | 58 +++++++++---------- Recyclable.Collections/RecyclableQueue.cs | 4 +- Recyclable.Collections/RecyclableStack.cs | 6 +- .../RecyclableListTests.cs | 4 +- 11 files changed, 63 insertions(+), 64 deletions(-) diff --git a/Recyclable.Collections/Recyclable.Collections.csproj b/Recyclable.Collections/Recyclable.Collections.csproj index c862297..5655d70 100644 --- a/Recyclable.Collections/Recyclable.Collections.csproj +++ b/Recyclable.Collections/Recyclable.Collections.csproj @@ -1,5 +1,4 @@ - net6.0 net6.0;net7.0 diff --git a/Recyclable.Collections/RecyclableDefaults.cs b/Recyclable.Collections/RecyclableDefaults.cs index 0c682ff..291809d 100644 --- a/Recyclable.Collections/RecyclableDefaults.cs +++ b/Recyclable.Collections/RecyclableDefaults.cs @@ -4,7 +4,6 @@ { public const int BlockIndexLimit = int.MaxValue; public const int BlockSize = 16_384; - public const int Capacity = 1; public const int InitialCapacity = 4; public const long MinItemsCountForParallelization = 850_000; public const int MinPooledArrayLength = 37; diff --git a/Recyclable.Collections/RecyclableList.Helpers.cs b/Recyclable.Collections/RecyclableList.Helpers.cs index 048a08d..af19b31 100644 --- a/Recyclable.Collections/RecyclableList.Helpers.cs +++ b/Recyclable.Collections/RecyclableList.Helpers.cs @@ -17,13 +17,14 @@ namespace Recyclable.Collections { Span arrayMemory = destinationArray.AsSpan(); arrayMemory = arrayMemory[destinationArrayIndex..]; + // TODO: Convert "/" & "%" to bit-shifting int startingArrayIndex = (int)(startingIndex / blockSize); startingIndex %= blockSize; - if (arrays.Count > 0) + if (arrays._count > 0) { ReadOnlySpan sourceMemory = arrays[0].AsSpan(); var maxToCopy = (int)Math.Min(blockSize - startingIndex, arrayMemory.Length); - if (arrays.Count == 1) + if (arrays._count == 1) { maxToCopy = Math.Min(maxToCopy, lastBlockSize); } @@ -33,7 +34,7 @@ namespace Recyclable.Collections arrayMemory = arrayMemory[maxToCopy..]; } - for (var arrayIdx = startingArrayIndex + 1; arrayIdx < arrays.Count - 1 && arrayMemory.Length > 0; arrayIdx++) + for (var arrayIdx = startingArrayIndex + 1; arrayIdx < arrays._count - 1 && arrayMemory.Length > 0; arrayIdx++) { ReadOnlySpan sourceMemory = arrays[arrayIdx].AsSpan(); var maxToCopy = Math.Min(blockSize, arrayMemory.Length); @@ -42,7 +43,7 @@ namespace Recyclable.Collections arrayMemory = arrayMemory[maxToCopy..]; } - if (arrays.Count > 1 && arrayMemory.Length > 0) + if (arrays._count > 1 && arrayMemory.Length > 0) { ReadOnlySpan sourceMemory = arrays[^1].AsSpan(); var maxToCopy = Math.Min(lastBlockSize, arrayMemory.Length); @@ -56,7 +57,7 @@ namespace Recyclable.Collections public static IEnumerable Enumerate(RecyclableList arrays, int chunkSize, long totalCount) { long currentCount = 0; - for (var arrayIdx = 0; (arrayIdx < arrays.Count) && (currentCount < totalCount); arrayIdx++) + for (var arrayIdx = 0; (arrayIdx < arrays._count) && (currentCount < totalCount); arrayIdx++) { var array = arrays[arrayIdx]; currentCount += Math.Min(chunkSize, totalCount); @@ -86,7 +87,7 @@ namespace Recyclable.Collections [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long LongIndexOf(RecyclableList arrays, int blockSize, T item, IEqualityComparer comparer) { - for (var arrayIdx = 0; arrayIdx < arrays.Count; arrayIdx++) + for (var arrayIdx = 0; arrayIdx < arrays._count; arrayIdx++) { var array = arrays[arrayIdx]; Span arrayMemory = array.AsSpan(); diff --git a/Recyclable.Collections/RecyclableList.cs b/Recyclable.Collections/RecyclableList.cs index cb0b8aa..dfc65d3 100644 --- a/Recyclable.Collections/RecyclableList.cs +++ b/Recyclable.Collections/RecyclableList.cs @@ -8,9 +8,9 @@ namespace Recyclable.Collections [Serializable] public sealed partial class RecyclableList : IList, IReadOnlyList, IDisposable { - private static readonly bool NeedsClearing = !typeof(T).IsValueType; + private static readonly bool _needsClearing = !typeof(T).IsValueType; - public static explicit operator ReadOnlySpan(RecyclableList source) => new(source._memoryBlock, 0, source.Count); + public static explicit operator ReadOnlySpan(RecyclableList source) => new(source._memoryBlock, 0, source._count); #nullable disable internal T[] _memoryBlock; @@ -59,17 +59,17 @@ namespace Recyclable.Collections return enumerator; } - private void AddRangeWithKnownCount(IEnumerable source, int targetItemIdx, int requiredAdditionalCapacity) + private void AddRangeWithKnownCount(IEnumerable source, int currentItemsCount, int requiredAdditionalCapacity) { - _capacity = RecyclableListHelpers.ResizeAndCopy(this, checked((int)BitOperations.RoundUpToPowerOf2((uint)(targetItemIdx + requiredAdditionalCapacity)))); + _capacity = RecyclableListHelpers.ResizeAndCopy(this, checked((int)BitOperations.RoundUpToPowerOf2((uint)(currentItemsCount + requiredAdditionalCapacity)))); Span memorySpan = new(_memoryBlock); foreach (var item in source) { - memorySpan[targetItemIdx++] = item; + memorySpan[currentItemsCount++] = item; } - _count = targetItemIdx; + _count = currentItemsCount; } public RecyclableList() @@ -136,7 +136,7 @@ namespace Recyclable.Collections AddRange(source); } - public RecyclableList(IEnumerable source, int initialCapacity = RecyclableDefaults.Capacity) + public RecyclableList(IEnumerable source, int initialCapacity = RecyclableDefaults.InitialCapacity) { if (initialCapacity >= RecyclableDefaults.InitialCapacity) { @@ -271,7 +271,7 @@ namespace Recyclable.Collections return; } - var sourceItemsCount = items.LongCount; + var sourceItemsCount = items._longCount; if (sourceItemsCount > int.MaxValue) { ThrowHelper.ThrowArgumentOutOfRangeException(nameof(items), $"The number of items exceeds the maximum capacity of {nameof(RecyclableList)}, equal {int.MaxValue}, equal {int.MaxValue}. Please consider using {nameof(RecyclableLongList)}, instead"); @@ -292,7 +292,7 @@ namespace Recyclable.Collections itemsSpan; int blockIndex, - sourceBlockSize = items.BlockSize, + sourceBlockSize = items._blockSize, lastBlockIndex = (int)(sourceItemsCount >> items._blockSizePow2BitShift) - 1; for (blockIndex = 0; blockIndex <= lastBlockIndex; blockIndex++) @@ -307,9 +307,9 @@ namespace Recyclable.Collections itemsSpan = new(items._memoryBlocks[blockIndex], 0, (int)sourceItemsCount); itemsSpan.CopyTo(targetSpan); } - else if (blockIndex <= items.LastBlockWithData) + else if (blockIndex <= items._lastBlockWithData) { - itemsSpan = new(items._memoryBlocks[blockIndex], 0, items.NextItemIndex); + itemsSpan = new(items._memoryBlocks[blockIndex], 0, items._nextItemIndex); itemsSpan.CopyTo(targetSpan); } @@ -358,7 +358,7 @@ namespace Recyclable.Collections return; } - if (NeedsClearing) + if (_needsClearing) { Array.Clear(_memoryBlock, 0, _count); } @@ -408,7 +408,7 @@ namespace Recyclable.Collections Array.Copy(_memoryBlock, index + 1, _memoryBlock, index, _count - index); } - if (NeedsClearing) + if (_needsClearing) { _memoryBlock[_count] = default; } @@ -435,7 +435,7 @@ namespace Recyclable.Collections Array.Copy(_memoryBlock, index + 1, _memoryBlock, index, _count - index); } - if (NeedsClearing) + if (_needsClearing) { _memoryBlock[_count] = default; } @@ -457,7 +457,7 @@ namespace Recyclable.Collections _version++; if (_count != 0) { - if (NeedsClearing) + if (_needsClearing) { Array.Clear(_memoryBlock, 0, _count); } diff --git a/Recyclable.Collections/RecyclableLongList.Enumerator.cs b/Recyclable.Collections/RecyclableLongList.Enumerator.cs index 65fb776..e02b82e 100644 --- a/Recyclable.Collections/RecyclableLongList.Enumerator.cs +++ b/Recyclable.Collections/RecyclableLongList.Enumerator.cs @@ -67,7 +67,7 @@ namespace Recyclable.Collections public void Reset() { - if (NeedsClearing) + if (_needsClearing) { _current = _default; } @@ -78,7 +78,7 @@ namespace Recyclable.Collections public void Dispose() { - if (NeedsClearing) + if (_needsClearing) { _current = _default; } diff --git a/Recyclable.Collections/RecyclableLongList.Helpers.cs b/Recyclable.Collections/RecyclableLongList.Helpers.cs index a6d327f..5077712 100644 --- a/Recyclable.Collections/RecyclableLongList.Helpers.cs +++ b/Recyclable.Collections/RecyclableLongList.Helpers.cs @@ -196,7 +196,7 @@ namespace Recyclable.Collections // We can now return the old memory block for all arrays itself if (sourceBlockCount >= RecyclableDefaults.MinPooledArrayLength) { - RecyclableArrayPool.ReturnShared(list._memoryBlocks!, NeedsClearing); + RecyclableArrayPool.ReturnShared(list._memoryBlocks!, _needsClearing); } } diff --git a/Recyclable.Collections/RecyclableLongList.VersionedEnumerator.cs b/Recyclable.Collections/RecyclableLongList.VersionedEnumerator.cs index a634914..ad86d10 100644 --- a/Recyclable.Collections/RecyclableLongList.VersionedEnumerator.cs +++ b/Recyclable.Collections/RecyclableLongList.VersionedEnumerator.cs @@ -86,7 +86,7 @@ namespace Recyclable.Collections throw new InvalidOperationException(); } - if (NeedsClearing) + if (_needsClearing) { _current = _default; } @@ -97,7 +97,7 @@ namespace Recyclable.Collections public void Dispose() { - if (NeedsClearing) + if (_needsClearing) { _current = _default; } diff --git a/Recyclable.Collections/RecyclableLongList.cs b/Recyclable.Collections/RecyclableLongList.cs index 2989c32..b6053b7 100644 --- a/Recyclable.Collections/RecyclableLongList.cs +++ b/Recyclable.Collections/RecyclableLongList.cs @@ -10,23 +10,32 @@ namespace Recyclable.Collections { public partial class RecyclableLongList : IList, IReadOnlyList, IDisposable { +#pragma warning disable CA1825 private static readonly T[][] _emptyMemoryBlocksArray = new T[0][]; private static readonly T[] _emptyBlockArray = new T[0]; +#pragma warning restore CA1825 private static readonly bool _defaultIsNull = default(T) == null; - private static readonly bool NeedsClearing = !typeof(T).IsValueType; + private static readonly bool _needsClearing = !typeof(T).IsValueType; internal int _blockSize; internal byte _blockSizePow2BitShift; internal int _blockSizeMinus1; - internal int _nextItemBlockIndex; - internal int _nextItemIndex; - private int _reservedBlockCount; - + internal long _capacity; + internal int _lastBlockWithData = RecyclableDefaults.ItemNotFoundIndex; + internal long _longCount; #nullable disable internal T[][] _memoryBlocks; #nullable restore + internal int _nextItemBlockIndex; + internal int _nextItemIndex; +#pragma warning disable IDE0032 + internal int _reservedBlockCount; +#pragma warning restore IDE0032 + internal ulong _version; - private long _capacity; + public int BlockSize => _blockSize; + public int BlockSizeMinus1 => _blockSizeMinus1; + public byte BlockSizePow2BitShift => _blockSizePow2BitShift; public long Capacity { get => _capacity; @@ -44,20 +53,11 @@ namespace Recyclable.Collections public int Count => checked((int)_longCount); public bool IsReadOnly => false; - internal int _lastBlockWithData = RecyclableDefaults.ItemNotFoundIndex; public int LastBlockWithData => _lastBlockWithData; - - internal long _longCount; public long LongCount => _longCount; - - public int ReservedBlockCount => _reservedBlockCount; - public int BlockSize => _blockSize; - public int BlockSizeMinus1 => _blockSizeMinus1; - public byte BlockSizePow2BitShift => _blockSizePow2BitShift; public int NextItemBlockIndex => _nextItemBlockIndex; public int NextItemIndex => _nextItemIndex; - - internal ulong _version; + public int ReservedBlockCount => _reservedBlockCount; public ulong Version => _version; private void AddRangeEnumerated(IEnumerable source, int growByCount) @@ -74,7 +74,7 @@ namespace Recyclable.Collections long capacity = _capacity; long available = capacity - copied; - Span memoryBlocksSpan = new(_memoryBlocks, 0, ReservedBlockCount); + Span memoryBlocksSpan = new(_memoryBlocks, 0, _reservedBlockCount); Span blockArraySpan; var memoryBlocksCount = memoryBlocksSpan.Length; while (true) @@ -155,7 +155,7 @@ namespace Recyclable.Collections blockSize = _blockSize; } - var memoryBlocksCount = ReservedBlockCount; + var memoryBlocksCount = _reservedBlockCount; memoryBlocksSpan = new(_memoryBlocks, 0, memoryBlocksCount); blockArraySpan = new(memoryBlocksSpan[targetBlockIdx], 0, blockSize); foreach (var item in source) @@ -440,12 +440,12 @@ namespace Recyclable.Collections public void AddRange(RecyclableList items) { - if (items.Count == 0) + if (items._count == 0) { return; } - long targetCapacity = _longCount + items.Count; + long targetCapacity = _longCount + items._count; if (_capacity < targetCapacity) { _capacity = Helpers.Resize(this, _blockSize, _blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)targetCapacity))); @@ -455,7 +455,7 @@ namespace Recyclable.Collections targetBlockIndex = _nextItemBlockIndex, memoryBlockCount = _reservedBlockCount; - Span itemsSpan = new(items.AsArray, 0, items.Count); + Span itemsSpan = new(items._memoryBlock, 0, items._count); Span memoryBlocksSpan = new(_memoryBlocks, 0, memoryBlockCount); Span targetBlockArraySpan = new(memoryBlocksSpan[targetBlockIndex], _nextItemIndex, blockSize - _nextItemIndex); while (targetBlockArraySpan.Length <= itemsSpan.Length) @@ -529,12 +529,12 @@ namespace Recyclable.Collections public void AddRange(RecyclableLongList items) { - if (items.LongCount == 0) + if (items._longCount == 0) { return; } - long itemsCount = items.LongCount, + long itemsCount = items._longCount, targetCapacity = _longCount + itemsCount; if (_capacity < targetCapacity) @@ -698,7 +698,7 @@ namespace Recyclable.Collections { if (items.Count >= RecyclableDefaults.MinPooledArrayLength) { - RecyclableArrayPool.ReturnShared(itemsBuffer, NeedsClearing); + RecyclableArrayPool.ReturnShared(itemsBuffer, _needsClearing); } _version++; @@ -753,7 +753,7 @@ namespace Recyclable.Collections int toRemoveIdx = 0; while (toRemoveIdx < memoryBlocksCount) { - RecyclableArrayPool.ReturnShared(memoryBlocks[toRemoveIdx++], NeedsClearing); + RecyclableArrayPool.ReturnShared(memoryBlocks[toRemoveIdx++], _needsClearing); } } @@ -970,7 +970,7 @@ namespace Recyclable.Collections _lastBlockWithData--; } - if (NeedsClearing) + if (_needsClearing) { #nullable disable new Span(_memoryBlocks[_nextItemBlockIndex])[_nextItemIndex] = default; @@ -988,7 +988,7 @@ namespace Recyclable.Collections { if (_blockSize >= RecyclableDefaults.MinPooledArrayLength) { - RecyclableArrayPool.ReturnShared(_memoryBlocks[index], NeedsClearing); + RecyclableArrayPool.ReturnShared(_memoryBlocks[index], _needsClearing); _memoryBlocks[index] = _emptyBlockArray; } else @@ -1038,7 +1038,7 @@ namespace Recyclable.Collections _lastBlockWithData--; } - if (NeedsClearing) + if (_needsClearing) { #nullable disable new Span(_memoryBlocks[_nextItemBlockIndex])[_nextItemIndex] = default; @@ -1076,7 +1076,7 @@ namespace Recyclable.Collections _lastBlockWithData--; } - if (NeedsClearing) + if (_needsClearing) { #nullable disable new Span(_memoryBlocks[_nextItemBlockIndex])[_nextItemIndex] = default; diff --git a/Recyclable.Collections/RecyclableQueue.cs b/Recyclable.Collections/RecyclableQueue.cs index b2bbbcd..4153c1e 100644 --- a/Recyclable.Collections/RecyclableQueue.cs +++ b/Recyclable.Collections/RecyclableQueue.cs @@ -144,11 +144,11 @@ namespace Recyclable.Collections try { // Remove in reversed order for performance savings - while (Memory.Count > 0) + while (Memory._count > 0) { try { - RemoveBlock(Memory.Count - 1); + RemoveBlock(Memory._count - 1); } #pragma warning disable RCS1075 // We want to try returning as many arrays, as possible, before the list is cleared. catch (Exception) diff --git a/Recyclable.Collections/RecyclableStack.cs b/Recyclable.Collections/RecyclableStack.cs index b8a2a2a..a108680 100644 --- a/Recyclable.Collections/RecyclableStack.cs +++ b/Recyclable.Collections/RecyclableStack.cs @@ -14,7 +14,7 @@ namespace Recyclable.Collections get => List._longCount; set => List._longCount = value; } - public bool IsReadOnly => List.IsReadOnly; + public bool IsReadOnly => false; public T this[int index] { get => this[(long)index]; set => this[(long)index] = value; } public T this[long index] { get => List[index]; set => List[index] = value; } @@ -46,9 +46,9 @@ namespace Recyclable.Collections { var toRemove = List[LongCount - 1]; LongCount--; - if ((List.Capacity * _blockSize) - LongCount == _blockSize) + if ((List._capacity * _blockSize) - LongCount == _blockSize) { - List.RemoveBlock(List.ReservedBlockCount - 1); + List.RemoveBlock(List._reservedBlockCount - 1); } return toRemove; diff --git a/Recyclable.CollectionsTests/RecyclableListTests.cs b/Recyclable.CollectionsTests/RecyclableListTests.cs index 8ed02c4..078952d 100644 --- a/Recyclable.CollectionsTests/RecyclableListTests.cs +++ b/Recyclable.CollectionsTests/RecyclableListTests.cs @@ -89,7 +89,7 @@ namespace Recyclable.CollectionsTests } // Validate - _ = list.Capacity.Should().Be(4); + _ = list.Capacity.Should().Be(RecyclableDefaults.InitialCapacity); _ = list.Count.Should().Be(0); _ = list.Should().BeEmpty(); } @@ -138,7 +138,7 @@ namespace Recyclable.CollectionsTests } // Validate - var expectedData = testData.Concat(testData).ToRecyclableLongList(); + using var expectedData = testData.Concat(testData).ToRecyclableLongList(); if (itemsCount > 0) {