Improve the performance of List<T>.Reverse
authorJustin Van Patten <jvp@justinvp.com>
Sun, 12 Jul 2015 00:44:53 +0000 (17:44 -0700)
committerJustin Van Patten <jvp@justinvp.com>
Tue, 14 Jul 2015 19:03:33 +0000 (12:03 -0700)
List<T>.Reverse is currently implemented in terms of the non-generic
Array.Reverse. Array.Reverse includes a fast path for a known set
of primitive types via a call into the runtime (see TrySZReverse).
Otherwise, it falls back to slower code paths that involve boxing
for non-primitive value types.

This commit changes List<T>.Reverse to use a generic implementation
of reverse that does not have the performance issue for
non-primitive value types.

src/mscorlib/src/System/Collections/Generic/List.cs

index 73e942e..8572dab 100644 (file)
@@ -918,9 +918,6 @@ namespace System.Collections.Generic {
         // which was previously located at index i will now be located at
         // index index + (index + count - i - 1).
         // 
-        // This method uses the Array.Reverse method to reverse the
-        // elements.
-        // 
         public void Reverse(int index, int count) {
             if (index < 0) {
                 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
@@ -933,7 +930,23 @@ namespace System.Collections.Generic {
             if (_size - index < count)
                 ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
             Contract.EndContractBlock();
-            Array.Reverse(_items, index, count);
+
+            // The non-generic Array.Reverse is not used because it does not perform
+            // well for non-primitive value types.
+            // If/when a generic Array.Reverse<T> becomes available, the below code
+            // can be deleted and replaced with a call to Array.Reverse<T>.
+            int i = index;
+            int j = index + count - 1;
+            T[] array = _items;
+            while (i < j)
+            {
+                T temp = array[i];
+                array[i] = array[j];
+                array[j] = temp;
+                i++;
+                j--;
+            }
+
             _version++;
         }