From ba4225e5d918f2657fbbebf18be4c7323583a8cf Mon Sep 17 00:00:00 2001 From: Levi Broderick Date: Mon, 7 May 2018 20:50:33 -0700 Subject: [PATCH] Speed up Array.Reverse by using ref reassignment (#17891) * Speed up Array.Reverse by using ref reassignment * Optimize MemoryExtensions.Reverse --- src/mscorlib/shared/System/MemoryExtensions.cs | 22 ++++++++++++--------- src/mscorlib/src/System/Array.cs | 27 +++++++++++++++----------- 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/src/mscorlib/shared/System/MemoryExtensions.cs b/src/mscorlib/shared/System/MemoryExtensions.cs index a706b7b..b4782dc 100644 --- a/src/mscorlib/shared/System/MemoryExtensions.cs +++ b/src/mscorlib/shared/System/MemoryExtensions.cs @@ -771,17 +771,21 @@ namespace System /// public static void Reverse(this Span span) { - ref T p = ref MemoryMarshal.GetReference(span); - int i = 0; - int j = span.Length - 1; - while (i < j) + if (span.Length <= 1) { - T temp = Unsafe.Add(ref p, i); - Unsafe.Add(ref p, i) = Unsafe.Add(ref p, j); - Unsafe.Add(ref p, j) = temp; - i++; - j--; + return; } + + ref T first = ref MemoryMarshal.GetReference(span); + ref T last = ref Unsafe.Add(ref Unsafe.Add(ref first, span.Length), -1); + do + { + T temp = first; + first = last; + last = temp; + first = ref Unsafe.Add(ref first, 1); + last = ref Unsafe.Add(ref last, -1); + } while (Unsafe.IsAddressLessThan(ref first, ref last)); } /// diff --git a/src/mscorlib/src/System/Array.cs b/src/mscorlib/src/System/Array.cs index 28a8d04..d8a958d 100644 --- a/src/mscorlib/src/System/Array.cs +++ b/src/mscorlib/src/System/Array.cs @@ -1528,6 +1528,9 @@ namespace System if (array.Rank != 1) ThrowHelper.ThrowRankException(ExceptionResource.Rank_MultiDimNotSupported); + if (length <= 1) + return; + bool r = TrySZReverse(array, index, length); if (r) return; @@ -1561,7 +1564,7 @@ namespace System ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); Reverse(array, 0, array.Length); } - + public static void Reverse(T[] array, int index, int length) { if (array == null) @@ -1573,17 +1576,19 @@ namespace System if (array.Length - index < length) ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); - ref T p = ref Unsafe.As(ref array.GetRawSzArrayData()); - int i = index; - int j = index + length - 1; - while (i < j) + if (length <= 1) + return; + + ref T first = ref Unsafe.Add(ref Unsafe.As(ref array.GetRawSzArrayData()), index); + ref T last = ref Unsafe.Add(ref Unsafe.Add(ref first, length), -1); + do { - T temp = Unsafe.Add(ref p, i); - Unsafe.Add(ref p, i) = Unsafe.Add(ref p, j); - Unsafe.Add(ref p, j) = temp; - i++; - j--; - } + T temp = first; + first = last; + last = temp; + first = ref Unsafe.Add(ref first, 1); + last = ref Unsafe.Add(ref last, -1); + } while (Unsafe.IsAddressLessThan(ref first, ref last)); } // Sorts the elements of an array. The sort compares the elements to each -- 2.7.4