RecyclableList performance improvements to pre-calculate the value of _blockSize - 1 & store it under _blockSizeMinus1

This commit is contained in:
mlemanczyk committed 2023-04-11 20:30:34 +02:00
1 parent abbd568c6b
commit 7c7740b27c
1 file changed
+22 -14
+22 -14
View File
@@ -16,6 +16,7 @@ namespace Recyclable.Collections
private int _blockSize; private int _blockSize;
private byte _blockSizePow2Shift; private byte _blockSizePow2Shift;
private int _blockSizeMinus1;
private int _nextItemBlockIndex; private int _nextItemBlockIndex;
private int _nextItemIndex; private int _nextItemIndex;
@@ -44,7 +45,7 @@ namespace Recyclable.Collections
set => _longCount = value; set => _longCount = value;
} }
public int ReservedBlockCount => checked((int)(_capacity >> _blockSizePow2Shift) + ((_capacity & (_blockSize - 1)) > 0 ? 1 : 0)); public int ReservedBlockCount => checked((int)(_capacity >> _blockSizePow2Shift) + ((_capacity & _blockSizeMinus1) > 0 ? 1 : 0));
public int BlockSize => _blockSize; public int BlockSize => _blockSize;
public int NextItemBlockIndex => _nextItemBlockIndex; public int NextItemBlockIndex => _nextItemBlockIndex;
public int NextItemIndex => _nextItemIndex; public int NextItemIndex => _nextItemIndex;
@@ -56,10 +57,10 @@ namespace Recyclable.Collections
int nextItemIndex = list._nextItemIndex; int nextItemIndex = list._nextItemIndex;
int blockSize = list._blockSize; int blockSize = list._blockSize;
int sourceBlockIndex = checked((int)((index + 1) >> list._blockSizePow2Shift)); int sourceBlockIndex = checked((int)((index + 1) >> list._blockSizePow2Shift));
int sourceItemIndex = checked((int)((index + 1) & (blockSize - 1))); int sourceItemIndex = checked((int)((index + 1) & list._blockSizeMinus1));
int targetBlockIndex = checked((int)(index >> list._blockSizePow2Shift)); int targetBlockIndex = checked((int)(index >> list._blockSizePow2Shift));
int targetItemIndex = checked((int)(index & (blockSize - 1))); int targetItemIndex = checked((int)(index & list._blockSizeMinus1));
int lastTakenBlockIndex = list.LastBlockWithData; int lastTakenBlockIndex = list.LastBlockWithData;
while (sourceBlockIndex < lastTakenBlockIndex || (sourceBlockIndex == lastTakenBlockIndex && (sourceItemIndex < nextItemIndex || sourceBlockIndex != list._nextItemBlockIndex))) while (sourceBlockIndex < lastTakenBlockIndex || (sourceBlockIndex == lastTakenBlockIndex && (sourceItemIndex < nextItemIndex || sourceBlockIndex != list._nextItemBlockIndex)))
@@ -345,6 +346,7 @@ namespace Recyclable.Collections
list._blockSizePow2Shift = (byte)MathUtils.GetPow2Shift(blockSize); list._blockSizePow2Shift = (byte)MathUtils.GetPow2Shift(blockSize);
list._blockSize = blockSize; list._blockSize = blockSize;
list._blockSizeMinus1 = blockSize - 1;
} }
list._capacity = newCapacity; list._capacity = newCapacity;
@@ -368,6 +370,7 @@ namespace Recyclable.Collections
if (_memoryBlocks!.Length > 0 && _blockSize != _memoryBlocks[0].Length) if (_memoryBlocks!.Length > 0 && _blockSize != _memoryBlocks[0].Length)
{ {
_blockSize = _memoryBlocks[0].Length; _blockSize = _memoryBlocks[0].Length;
_blockSizeMinus1 = _blockSize - 1;
_blockSizePow2Shift = (byte)(31 - BitOperations.LeadingZeroCount((uint)_blockSize)); _blockSizePow2Shift = (byte)(31 - BitOperations.LeadingZeroCount((uint)_blockSize));
if (_blockSize >= RecyclableDefaults.MinPooledArrayLength) if (_blockSize >= RecyclableDefaults.MinPooledArrayLength)
{ {
@@ -377,11 +380,13 @@ namespace Recyclable.Collections
else else
{ {
_blockSize = minBlockSize; _blockSize = minBlockSize;
_blockSizeMinus1 = minBlockSize - 1;
} }
} }
else else
{ {
_blockSize = checked((int)BitOperations.RoundUpToPowerOf2((uint)minBlockSize)); _blockSize = checked((int)BitOperations.RoundUpToPowerOf2((uint)minBlockSize));
_blockSizeMinus1 = _blockSize - 1;
_blockSizePow2Shift = (byte)(31 - BitOperations.LeadingZeroCount((uint)_blockSize)); _blockSizePow2Shift = (byte)(31 - BitOperations.LeadingZeroCount((uint)_blockSize));
_blockArrayPool = _blockSize >= RecyclableDefaults.MinPooledArrayLength _blockArrayPool = _blockSize >= RecyclableDefaults.MinPooledArrayLength
? blockArrayPool ?? RecyclableArrayPool<T>.Shared(_blockSize) ? blockArrayPool ?? RecyclableArrayPool<T>.Shared(_blockSize)
@@ -405,9 +410,10 @@ namespace Recyclable.Collections
_blockSizePow2Shift = (byte)(31 - BitOperations.LeadingZeroCount((uint)minBlockSize)); _blockSizePow2Shift = (byte)(31 - BitOperations.LeadingZeroCount((uint)minBlockSize));
_capacity = Resize(this, minBlockSize, _blockSizePow2Shift, expectedItemsCount.Value); _capacity = Resize(this, minBlockSize, _blockSizePow2Shift, expectedItemsCount.Value);
if (_memoryBlocks?.Length > 0 && minBlockSize != _memoryBlocks[0].Length) if (_memoryBlocks!.Length > 0 && minBlockSize != _memoryBlocks[0].Length)
{ {
_blockSize = _memoryBlocks[0].Length; _blockSize = _memoryBlocks[0].Length;
_blockSizeMinus1 = _blockSize - 1;
_blockSizePow2Shift = (byte)(31 - BitOperations.LeadingZeroCount((uint)minBlockSize)); _blockSizePow2Shift = (byte)(31 - BitOperations.LeadingZeroCount((uint)minBlockSize));
if (_blockSize >= RecyclableDefaults.MinPooledArrayLength) if (_blockSize >= RecyclableDefaults.MinPooledArrayLength)
{ {
@@ -417,6 +423,7 @@ namespace Recyclable.Collections
else else
{ {
_blockSize = minBlockSize; _blockSize = minBlockSize;
_blockSizeMinus1 = minBlockSize - 1;
} }
} }
else else
@@ -426,6 +433,7 @@ namespace Recyclable.Collections
? blockArrayPool ?? RecyclableArrayPool<T>.Shared(_blockSize) ? blockArrayPool ?? RecyclableArrayPool<T>.Shared(_blockSize)
: RecyclableArrayPool<T>.Null; : RecyclableArrayPool<T>.Null;
_blockSizeMinus1 = _blockSize - 1;
_blockSizePow2Shift = (byte)(31 - BitOperations.LeadingZeroCount((uint)_blockSize)); _blockSizePow2Shift = (byte)(31 - BitOperations.LeadingZeroCount((uint)_blockSize));
_memoryBlocks = _emptyMemoryBlocksArray; _memoryBlocks = _emptyMemoryBlocksArray;
} }
@@ -435,14 +443,14 @@ namespace Recyclable.Collections
public T this[long index] public T this[long index]
{ {
get => _memoryBlocks[index >> _blockSizePow2Shift][index & (_blockSize - 1)]; get => _memoryBlocks[index >> _blockSizePow2Shift][index & _blockSizeMinus1];
set => new Span<T>(_memoryBlocks[checked((int)(index >> _blockSizePow2Shift))])[checked((int)(index & (_blockSize - 1)))] = value; set => new Span<T>(_memoryBlocks[checked((int)(index >> _blockSizePow2Shift))])[checked((int)(index & _blockSizeMinus1))] = value;
} }
public T this[int index] public T this[int index]
{ {
get => _memoryBlocks[index >> _blockSizePow2Shift][index & (_blockSize - 1)]; get => _memoryBlocks[index >> _blockSizePow2Shift][index & _blockSizeMinus1];
set => new Span<T>(_memoryBlocks[index >> _blockSizePow2Shift])[index & (_blockSize - 1)] = value; set => new Span<T>(_memoryBlocks[index >> _blockSizePow2Shift])[index & _blockSizeMinus1] = value;
} }
public T[][] MemoryBlocks { get => _memoryBlocks; } public T[][] MemoryBlocks { get => _memoryBlocks; }
@@ -604,14 +612,14 @@ namespace Recyclable.Collections
} }
} }
if ((targetCapacity & (blockSize - 1)) == 0) if ((targetCapacity & _blockSizeMinus1) == 0)
{ {
_nextItemIndex = 0; _nextItemIndex = 0;
_nextItemBlockIndex = targetBlockIndex + 1; _nextItemBlockIndex = targetBlockIndex + 1;
} }
else else
{ {
_nextItemIndex = checked((int)(targetCapacity & (blockSize - 1))); _nextItemIndex = checked((int)(targetCapacity & _blockSizeMinus1));
_nextItemBlockIndex = targetBlockIndex; _nextItemBlockIndex = targetBlockIndex;
} }
@@ -719,7 +727,7 @@ namespace Recyclable.Collections
} }
} }
public void AddRange(IEnumerable<T> source, int growByCount = RecyclableDefaults.MinPooledArrayLength) public void AddRange(IEnumerable<T> source, int growByCount = RecyclableDefaults.BlockSize)
{ {
if (source is RecyclableList<T> sourceRecyclableList) if (source is RecyclableList<T> sourceRecyclableList)
{ {
@@ -843,7 +851,7 @@ namespace Recyclable.Collections
} }
else else
{ {
_nextItemIndex = _blockSize - 1; _nextItemIndex = _blockSizeMinus1;
_nextItemBlockIndex--; _nextItemBlockIndex--;
} }
@@ -902,7 +910,7 @@ namespace Recyclable.Collections
} }
else else
{ {
_nextItemIndex = _blockSize - 1; _nextItemIndex = _blockSizeMinus1;
_nextItemBlockIndex--; _nextItemBlockIndex--;
} }
@@ -934,7 +942,7 @@ namespace Recyclable.Collections
} }
else else
{ {
_nextItemIndex = _blockSize - 1; _nextItemIndex = _blockSizeMinus1;
_nextItemBlockIndex--; _nextItemBlockIndex--;
} }