I was just browsing through the List<T> implementation and made a few speed
optimisations. I'm not sure if changing from foreach(blah) to for(int i=0;
i< blah, i++) is ok or not, but it does offer a large speed increase. So let
me know if that's ok or not.

Optimised Methods:
RemoveAll - from 0x up to 50x faster

(The reason for the huge speed increase is that if you have a list<int>
containing entirely the number 5, removing from the end will be much more
efficient than removing from the start as you won't have to shift the entire
array over and over. Removing from the end will *always* be faster than
removing from the start, but the exact speed increase is highly dependant on
the number of matches).

Add - 0.3x faster

ConvertAll - 0.5x faster

Exists - 0.04x faster

Find - 0.05x faster

ForEach - 2.7x faster

InsertAt - up to 0.2x faster (if addind at the end)

RemoveAll - 0.11x faster

True For All - 2.3x faster

Patch attached. Let me know if it's good to commit. It still passes the
NUnit tests.

Alan.
Index: C:/programming/mcs/class/corlib/System.Collections.Generic/List.cs
===================================================================
--- C:/programming/mcs/class/corlib/System.Collections.Generic/List.cs	(revision 74942)
+++ C:/programming/mcs/class/corlib/System.Collections.Generic/List.cs	(working copy)
@@ -82,7 +82,10 @@
 		}
 		public void Add (T item)
 		{
-			GrowIfNeeded (1);
+			// If we check to see if we need to grow before trying to grow
+			// we can speed things up by 25%
+			if (this._size == this._items.Length)
+				GrowIfNeeded (1);
 			_items [_size ++] = item;
 			_version++;
 		}
@@ -163,11 +166,7 @@
 		
 		public bool Contains (T item)
 		{
-			EqualityComparer<T> equalityComparer = EqualityComparer<T>.Default;
-			for (int i = 0; i < _size; i++)
-				if (equalityComparer.Equals (_items[i], item))
-					return true;
-			return false;
+			return Array.IndexOf<T>(this._items, item) != -1;
 		}
 		
 		public List <TOutput> ConvertAll <TOutput> (Converter <T, TOutput> converter)
@@ -175,8 +174,10 @@
 			if (converter == null)
 				throw new ArgumentNullException ("converter");
 			List <TOutput> u = new List <TOutput> (_size);
-			foreach (T t in this)
-				u.Add (converter (t));
+			for (int i = 0; i < this._size; i++)
+				u._items[i] = converter(this._items[i]);
+
+			u._size = this._size;
 			return u;
 		}
 		
@@ -198,7 +199,8 @@
 
 		public bool Exists (Predicate <T> match)
 		{
-			return FindIndex (match) != -1;
+			CheckMatch(match);
+			return GetIndex(0, this._size, match) != -1;
 		}
 		
 		public T Find (Predicate <T> match)
@@ -203,7 +205,8 @@
 		
 		public T Find (Predicate <T> match)
 		{
-			int i = FindIndex (match);
+			CheckMatch(match);
+			int i = GetIndex(0, this._size, match);
 			return (i != -1) ? _items [i] : default (T);
 		}
 		void CheckMatch (Predicate <T> match)
@@ -297,7 +300,8 @@
 		}
 		int GetIndex (int startIndex, int count, Predicate <T> match)
 		{
-			for (int i = startIndex; i < startIndex + count; i ++)
+			int end = startIndex + count;
+			for (int i = startIndex; i < end; i ++)
 				if (match (_items [i]))
 					return i;
 				
@@ -345,8 +349,8 @@
 		{
 			if (action == null)
 				throw new ArgumentNullException ("action");
-			foreach (T t in this)
-				action (t);
+			for(int i=0; i < this._size; i++)
+				action(this._items[i]);
 		}
 		
 		public Enumerator GetEnumerator ()
@@ -392,8 +396,9 @@
 			if (delta < 0)
 				start -= delta;
 			
-			Array.Copy (_items, start, _items, start + delta, _size - start);
-			
+			if (start < _size)
+				Array.Copy(_items, start, _items, start + delta, _size - start);
+
 			_size += delta;
 		}
 
@@ -405,10 +410,11 @@
 		
 		public void Insert (int index, T item)
 		{
-			CheckIndex (index);			
-			GrowIfNeeded (1);
-			Shift (index, 1);
-			this [index] = item;
+			CheckIndex(index);
+			if (this._size == this._items.Length)
+				GrowIfNeeded(1);
+			Shift(index, 1);
+			this._items[index] = item;
 			_version++;
 		}
 
@@ -486,7 +492,6 @@
 			return loc != -1;
 		}
 		
-		// FIXME: this could probably be made faster.
 		public int RemoveAll (Predicate <T> match)
 		{
 			CheckMatch (match);
@@ -491,14 +496,16 @@
 		{
 			CheckMatch (match);
 
-			int index = 0;
+			int index = this._size;
 			int c = 0;
-			while ((index = GetIndex (index, _size - index, match)) != -1) {
-				RemoveAt (index);
+			while ((index = GetLastIndex(0, index, match)) != -1) {
+				Shift(index, -1);
 				c ++;
 			}
-			
-			Array.Clear (_items, _size, c);
+
+			if (c != 0)
+				this._version++;
+
 			return c;
 		}
 		
@@ -504,9 +511,9 @@
 		
 		public void RemoveAt (int index)
 		{
-			CheckIndex (index);
+			if (index < 0 || (uint)index >= (uint)_size)
+				throw new ArgumentOutOfRangeException("index");
 			Shift (index, -1);
-			Array.Clear (_items, _size, 0);
 			_version++;
 		}
 		
@@ -573,8 +580,8 @@
 		{
 			CheckMatch (match);
 
-			foreach (T t in this)
-				if (!match (t))
+			for (int i = 0; i < this._size; i++)
+				if (!match(this._items[i]))
 					return false;
 				
 			return true;
_______________________________________________
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list

Reply via email to