From 5a9fe7540e047c554f37359e759c55a678a68bfc Mon Sep 17 00:00:00 2001 From: sakno Date: Mon, 16 Oct 2023 11:34:45 +0300 Subject: [PATCH] Optimized version for reference types (#193) --- src/DotNext/Span.cs | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/DotNext/Span.cs b/src/DotNext/Span.cs index a9948711e..9b8d6369e 100644 --- a/src/DotNext/Span.cs +++ b/src/DotNext/Span.cs @@ -762,34 +762,35 @@ public static ReadOnlySpan Contravariance(this ReadOnlySpan /// The first span. /// The second span. /// The length of is not of the same length as . - public static unsafe void Swap(this Span x, Span y) + public static void Swap(this Span x, Span y) { if (x.Length != y.Length) throw new ArgumentOutOfRangeException(nameof(y)); var bufferSize = Math.Min(MemoryRental.StackallocThreshold, x.Length); - MemoryRental buffer; if (RuntimeHelpers.IsReferenceOrContainsReferences()) { - buffer = new(bufferSize); + T[] buffer = ArrayPool.Shared.Rent(bufferSize); + Swap(x, y, buffer); + ArrayPool.Shared.Return(buffer, clearArray: true); } else { - // Only T without references inside can be allocated on the stack. - // GC cannot track references placed on the stack using `localloc` IL instruction. - void* ptr = stackalloc byte[checked(Unsafe.SizeOf() * bufferSize)]; - buffer = new Span(ptr, bufferSize); + unsafe + { + // Only T without references inside can be allocated on the stack. + // GC cannot track references placed on the stack using `localloc` IL instruction. + void* buffer = stackalloc byte[checked(Unsafe.SizeOf() * bufferSize)]; + Swap(x, y, new Span(buffer, bufferSize)); + } } - Swap(x, y, buffer.Span); - buffer.Dispose(); - static void Swap(Span x, Span y, Span buffer) { Debug.Assert(x.Length == y.Length); Debug.Assert(buffer.IsEmpty is false); - while (x.Length > buffer.Length) + while (x.Length >= buffer.Length) { SwapCore(TrimLengthCore(x, buffer.Length, out x), TrimLengthCore(y, buffer.Length, out y), buffer); }