* List.cs (FindAll): Optimize FindAll using a bitmask to
* determine
the number of positive matches, this increases the performance
in
all cases below 10,000,000 elements extensively:
100 elements:
old method: 00:00:00.
0126610 (26x)
stackalloc bit method: 00:00:00.
0004750 (1x)
array bit method: 00:00:00.
0010700 (2x)
heap bit method: 00:00:00.
0038830 (8x)
1,000 elements:
old method: 00:00:00.
0139250 (24x)
stackalloc bit method: 00:00:00.
0005670 (1x)
array bit method: 00:00:00.
0010890 (2x)
heap bit method: 00:00:00.
0034920 (6x)
10,000 elements:
old method: 00:00:00.
0136110 (12x)
stackalloc bit method: 00:00:00.
0011240 (1x)
array bit method: 00:00:00.
0016450 (1.4x)
heap bit method: 00:00:00.
0043110 (3x)
50,000 elements:
old method: 00:00:00.
0175970 (3x)
stackalloc bit method: 00:00:00.
0085630 (1.5x)
array bit method: 00:00:00.
0055010 (1x)
heap bit method: 00:00:00.
0099590 (1.8x)
100,000 elements:
old method: 00:00:00.
0210330 (2x)
array bit method: 00:00:00.
0100430 (1x)
heap bit method: 00:00:00.
0154150 (1.5x)
1,000,000 elements:
old method: 00:00:00.
1243730 (1.2x)
array bit method: 00:00:00.
0973110 (1x)
heap bit method: 00:00:00.
1285650 (1.3x)
10,000,000 elements:
old method: 00:00:00.
9252570 (1x)
array bit method: 00:00:00.
9632300 ( 1.05x)
heap bit method: 00:00:01.
1098490 (1.20x)
svn path=/trunk/mcs/; revision=74694
+2007-03-20 Juan Cristóbal Olivares <juancri@gmail.com>
+
+ * List.cs (FindAll): Optimize FindAll using a bitmask to determine
+ the number of positive matches, this increases the performance in
+ all cases below 10,000,000 elements extensively:
+
+ 100 elements:
+ old method: 00:00:00.0126610 (26x)
+ stackalloc bit method: 00:00:00.0004750 (1x)
+ array bit method: 00:00:00.0010700 (2x)
+ heap bit method: 00:00:00.0038830 (8x)
+
+ 1,000 elements:
+ old method: 00:00:00.0139250 (24x)
+ stackalloc bit method: 00:00:00.0005670 (1x)
+ array bit method: 00:00:00.0010890 (2x)
+ heap bit method: 00:00:00.0034920 (6x)
+
+ 10,000 elements:
+ old method: 00:00:00.0136110 (12x)
+ stackalloc bit method: 00:00:00.0011240 (1x)
+ array bit method: 00:00:00.0016450 (1.4x)
+ heap bit method: 00:00:00.0043110 (3x)
+
+ 50,000 elements:
+ old method: 00:00:00.0175970 (3x)
+ stackalloc bit method: 00:00:00.0085630 (1.5x)
+ array bit method: 00:00:00.0055010 (1x)
+ heap bit method: 00:00:00.0099590 (1.8x)
+
+ 100,000 elements:
+ old method: 00:00:00.0210330 (2x)
+ array bit method: 00:00:00.0100430 (1x)
+ heap bit method: 00:00:00.0154150 (1.5x)
+
+ 1,000,000 elements:
+ old method: 00:00:00.1243730 (1.2x)
+ array bit method: 00:00:00.0973110 (1x)
+ heap bit method: 00:00:00.1285650 (1.3x)
+
+ 10,000,000 elements:
+ old method: 00:00:00.9252570 (1x)
+ array bit method: 00:00:00.9632300 ( 1.05x)
+ heap bit method: 00:00:01.1098490 (1.20x)
+
2007-03-08 David Mitchell <dmitchell@logos.com>
* List.cs: Fix the case where List.set_Item(int index) throws
throw new ArgumentNullException ("match");
}
- // Maybe we could make this faster. For example, you could
- // make a bit set with stackalloc for which elements to copy
- // then you could size the array correctly.
public List <T> FindAll (Predicate <T> match)
{
- CheckMatch (match);
- List <T> f = new List <T> ();
-
- foreach (T t in this)
- if (match (t))
- f.Add (t);
+ this.CheckMatch (match);
+ if (this._size <= 0x10000) // <= 8 * 1024 * 8 (8k in stack)
+ return this.FindAllStackBits (match);
+ else
+ return this.FindAllList (match);
+ }
+
+ private List <T> FindAllStackBits (Predicate <T> match)
+ {
+ unsafe
+ {
+ uint *bits = stackalloc uint [(this._size / 32) + 1];
+ uint *ptr = bits;
+ int found = 0;
+ uint bitmask = 0x80000000;
+
+ for (int i = 0; i < this._size; i++)
+ {
+ if (match (this._items [i]))
+ {
+ (*ptr) = (*ptr) | bitmask;
+ found++;
+ }
+
+ bitmask = bitmask >> 1;
+ if (bitmask == 0)
+ {
+ ptr++;
+ bitmask = 0x80000000;
+ }
+ }
+
+ List <T> results = new List <T> (found);
+ bitmask = 0x80000000;
+ ptr = bits;
+ for (int i = 0; i < this._size; i++)
+ {
+ if (((*ptr) & bitmask) == bitmask)
+ results.Add (this._items [i]);
+
+ bitmask = bitmask >> 1;
+ if (bitmask == 0)
+ {
+ ptr++;
+ bitmask = 0x80000000;
+ }
+ }
+
+ return results;
+ }
+ }
+
+ private List <T> FindAllList (Predicate <T> match)
+ {
+ List <T> results = new List <T> ();
+ for (int i = 0; i < this._size; i++)
+ if (match (this._items [i]))
+ results.Add (this._items [i]);
- return f;
+ return results;
}
public int FindIndex (Predicate <T> match)
}
[Test]
- public void FindAllTest ()
+ public void FindAllSmallTest ()
{
List <int> findings = _list1.FindAll (FindMultipleOfFour);
Assert.AreEqual (4, findings.Count);
Assert.IsNotNull (findings);
Assert.AreEqual (0, findings.Count);
}
+
+ [Test]
+ public void FindAllMediumTest ()
+ {
+ List <int> integers = new List <int> (10000);
+ for (int i = 1; i <= 10000; i++)
+ integers.Add (i);
+
+ List <int> results = integers.FindAll (FindMultipleOfFour);
+
+ Assert.IsNotNull (results);
+ Assert.AreEqual (2500, results.Count);
+
+ results = integers.FindAll (FindMultipleOfTwelve);
+
+ Assert.IsNotNull (results);
+ Assert.AreEqual (833, results.Count);
+ }
+
+ [Test]
+ public void FindAllLargeTest ()
+ {
+ List <int> integers = new List <int> (70000);
+ for (int i = 1; i <= 80000; i++)
+ integers.Add (i);
+
+ List <int> results = integers.FindAll (FindMultipleOfFour);
+
+ Assert.IsNotNull (results);
+ Assert.AreEqual (20000, results.Count);
+
+ results = integers.FindAll (FindMultipleOfTwelve);
+
+ Assert.IsNotNull (results);
+ Assert.AreEqual (6666, results.Count);
+ }
[Test, ExpectedException (typeof (ArgumentNullException))]
public void FindAllNullTest ()
fi
topdir=../../..
-NUNITCONSOLE=$topdir/nunit20/nunit-console.exe
+NUNITCONSOLE=$topdir/class/lib/net_2_0/nunit-console.exe
MONO_PATH=$topdir/nunit20:$topdir/class/lib:.
for i in $@; do