diff --git a/Recyclable.Collections/RecyclableList.Helpers.cs b/Recyclable.Collections/RecyclableList.Helpers.cs index af19b31..4b84942 100644 --- a/Recyclable.Collections/RecyclableList.Helpers.cs +++ b/Recyclable.Collections/RecyclableList.Helpers.cs @@ -130,7 +130,7 @@ namespace Recyclable.Collections } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] - public static int ResizeAndCopy(RecyclableList sourceList, int newSize) + public static int ResizeAndCopy(RecyclableList sourceList, int oldSize, int newSize) { T[] oldMemoryBlock = sourceList._memoryBlock; sourceList._memoryBlock = newSize >= RecyclableDefaults.MinPooledArrayLength @@ -140,7 +140,7 @@ namespace Recyclable.Collections // & WAS SLOWER WITHOUT // & WAS SLOWER AS ARRAY - new Span(oldMemoryBlock, 0, sourceList._count).CopyTo(sourceList._memoryBlock); + new Span(oldMemoryBlock, 0, oldSize).CopyTo(sourceList._memoryBlock); if (oldMemoryBlock.Length >= RecyclableDefaults.MinPooledArrayLength) { diff --git a/Recyclable.Collections/RecyclableList.cs b/Recyclable.Collections/RecyclableList.cs index dfc65d3..68aee3b 100644 --- a/Recyclable.Collections/RecyclableList.cs +++ b/Recyclable.Collections/RecyclableList.cs @@ -36,8 +36,7 @@ namespace Recyclable.Collections { if (targetItemIndex + growByCount > capacity) { - _count = targetItemIndex; - capacity = RecyclableListHelpers.ResizeAndCopy(this, checked((int)BitOperations.RoundUpToPowerOf2((uint)(targetItemIndex + growByCount)))); + capacity = RecyclableListHelpers.ResizeAndCopy(this, targetItemIndex, checked((int)BitOperations.RoundUpToPowerOf2((uint)(targetItemIndex + growByCount)))); memorySpan = new(_memoryBlock); available = capacity - targetItemIndex; } @@ -61,7 +60,7 @@ namespace Recyclable.Collections private void AddRangeWithKnownCount(IEnumerable source, int currentItemsCount, int requiredAdditionalCapacity) { - _capacity = RecyclableListHelpers.ResizeAndCopy(this, checked((int)BitOperations.RoundUpToPowerOf2((uint)(currentItemsCount + requiredAdditionalCapacity)))); + _capacity = RecyclableListHelpers.ResizeAndCopy(this, currentItemsCount, checked((int)BitOperations.RoundUpToPowerOf2((uint)(currentItemsCount + requiredAdditionalCapacity)))); Span memorySpan = new(_memoryBlock); foreach (var item in source) @@ -175,7 +174,7 @@ namespace Recyclable.Collections { if (_capacity != value) { - _capacity = RecyclableListHelpers.ResizeAndCopy(this, checked((int)BitOperations.RoundUpToPowerOf2((uint)value))); + _capacity = RecyclableListHelpers.ResizeAndCopy(this, _count, checked((int)BitOperations.RoundUpToPowerOf2((uint)value))); _version++; } } @@ -203,7 +202,7 @@ namespace Recyclable.Collections { if (_capacity < _count + items.Length) { - _capacity = RecyclableListHelpers.ResizeAndCopy(this, checked((int)BitOperations.RoundUpToPowerOf2((uint)(_count + items.Length)))); + _capacity = RecyclableListHelpers.ResizeAndCopy(this, _count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(_count + items.Length)))); } new Span(items).CopyTo(new Span(_memoryBlock, _count, items.Length)); @@ -216,7 +215,7 @@ namespace Recyclable.Collections { if (_capacity < _count + items.Length) { - _capacity = RecyclableListHelpers.ResizeAndCopy(this, checked((int)BitOperations.RoundUpToPowerOf2((uint)(_count + items.Length)))); + _capacity = RecyclableListHelpers.ResizeAndCopy(this, _count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(_count + items.Length)))); } items.CopyTo(new Span(_memoryBlock, _count, items.Length)); @@ -229,7 +228,7 @@ namespace Recyclable.Collections { if (_capacity < _count + items.Count) { - _capacity = RecyclableListHelpers.ResizeAndCopy(this, checked((int)BitOperations.RoundUpToPowerOf2((uint)(_count + items.Count)))); + _capacity = RecyclableListHelpers.ResizeAndCopy(this, _count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(_count + items.Count)))); } items.CopyTo(_memoryBlock, _count); @@ -242,7 +241,7 @@ namespace Recyclable.Collections { if (_capacity < _count + items.Count) { - _capacity = RecyclableListHelpers.ResizeAndCopy(this, checked((int)BitOperations.RoundUpToPowerOf2((uint)(_count + items.Count)))); + _capacity = RecyclableListHelpers.ResizeAndCopy(this, _count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(_count + items.Count)))); } items.CopyTo(_memoryBlock, _count); @@ -255,7 +254,7 @@ namespace Recyclable.Collections { if (_capacity < _count + items._count) { - _capacity = RecyclableListHelpers.ResizeAndCopy(this, checked((int)BitOperations.RoundUpToPowerOf2((uint)(_count + items._count)))); + _capacity = RecyclableListHelpers.ResizeAndCopy(this, _count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(_count + items._count)))); } new Span(items._memoryBlock, 0, items._count).CopyTo(new Span(_memoryBlock, _count, items._count)); @@ -271,24 +270,26 @@ namespace Recyclable.Collections return; } - var sourceItemsCount = items._longCount; + int oldCount = _count; + long 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"); } - if (_count + sourceItemsCount > int.MaxValue) + 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 = _count + (int)sourceItemsCount; + int targetCapacity = oldCount + (int)sourceItemsCount; if (_capacity < targetCapacity) { - _capacity = RecyclableListHelpers.ResizeAndCopy(this, checked((int)BitOperations.RoundUpToPowerOf2((uint)targetCapacity))); + _capacity = RecyclableListHelpers.ResizeAndCopy(this, oldCount, checked((int)BitOperations.RoundUpToPowerOf2((uint)targetCapacity))); } - Span targetSpan = new Span(_memoryBlock)[_count..], + // TODO: Avoid unnecessary range operator - pass as arguments instead. + Span targetSpan = new Span(_memoryBlock)[oldCount..], itemsSpan; int blockIndex, @@ -382,7 +383,7 @@ namespace Recyclable.Collections int oldCount = _count; if (_capacity < oldCount + 1) { - _capacity = RecyclableListHelpers.ResizeAndCopy(this, checked((int)BitOperations.RoundUpToPowerOf2((uint)oldCount + 1))); + _capacity = RecyclableListHelpers.ResizeAndCopy(this, oldCount, checked((int)BitOperations.RoundUpToPowerOf2((uint)oldCount + 1))); } if (index < oldCount)