diff --git a/Recyclable.Collections/RecyclableList.Helpers.cs b/Recyclable.Collections/RecyclableList.Helpers.cs index c1914b0..10322f3 100644 --- a/Recyclable.Collections/RecyclableList.Helpers.cs +++ b/Recyclable.Collections/RecyclableList.Helpers.cs @@ -227,6 +227,35 @@ namespace Recyclable.Collections private static readonly bool NeedsClearing = !typeof(T).IsValueType; + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] + public static void ResizeAndCopy(RecyclableList list) + { + // TODO: Measure performance + // T[] newMemoryBlock = RecyclableListHelpers._arrayPool.Rent(_capacity <<= 1); + T[] oldMemoryBlock = list._memoryBlock; + list._memoryBlock = (list._capacity <<= 1) < RecyclableDefaults.MinPooledArrayLength + ? new T[list._capacity] + : _arrayPool.Rent(list._capacity); + + // & WAS SLOWER WITHOUT + new Span(oldMemoryBlock).CopyTo(list._memoryBlock); + + if (oldMemoryBlock.Length >= RecyclableDefaults.MinPooledArrayLength) + { + // TODO: Measure gain vs relying on arrayPool to clear + //if (NeedsClearing) + //{ + // Array.Clear(source); + //} + + // // If anything, it has been already cleared above, so we don't need to repeat it. + _arrayPool.Return(oldMemoryBlock, NeedsClearing); + } + + // list._memoryBlock = newMemoryBlock; + list._capacity = list._memoryBlock.Length; + } + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] public static void ResizeAndCopy(RecyclableList sourceList, int newSize) { diff --git a/Recyclable.Collections/RecyclableList.cs b/Recyclable.Collections/RecyclableList.cs index 2c51c62..c50fe3f 100644 --- a/Recyclable.Collections/RecyclableList.cs +++ b/Recyclable.Collections/RecyclableList.cs @@ -183,43 +183,12 @@ namespace Recyclable.Collections public bool IsReadOnly => false; - [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] - private void ResizeAndCopy() - { - // TODO: Measure performance - // ArrayPool arrayPool = _arrayPool; - // TODO: Measure performance after RecyclableArrayPool is reworked - // T[] newMemoryBlock = RecyclableListHelpers._arrayPool.Rent(_capacity <<= 1); - T[] newMemoryBlock = (_capacity <<= 1) >= RecyclableDefaults.MinPooledArrayLength - ? RecyclableListHelpers._arrayPool.Rent(_capacity) - : new T[_capacity]; - - // & WAS SLOWER WITHOUT - T[] oldMemoryBlock = _memoryBlock; - new Span(oldMemoryBlock).CopyTo(newMemoryBlock); - - if (oldMemoryBlock.Length >= RecyclableDefaults.MinPooledArrayLength) - { - // TODO: Measure gain vs relying on arrayPool to clear - //if (NeedsClearing) - //{ - // Array.Clear(source); - //} - - // // If anything, it has been already cleared above, so we don't need to repeat it. - RecyclableListHelpers._arrayPool.Return(oldMemoryBlock, NeedsClearing); - } - - _memoryBlock = newMemoryBlock; - _capacity = newMemoryBlock.Length; - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Add(T item) { if (_count == _capacity) { - ResizeAndCopy(); + RecyclableListHelpers.ResizeAndCopy(this); } _memoryBlock[_count++] = item;