LINQ-to-Objects
Nothing answers a question like this like a benchmark:
(Updated)
class Program
{
const int N = 10000;
volatile private static int s_val;
static void DoTest(IEnumerable<int> data, int[] selectors) {
Stopwatch s;
// Using .Single(predicate)
s = Stopwatch.StartNew();
foreach (var t in selectors) {
s_val = data.Single(x => x == t);
}
s.Stop();
Console.WriteLine(" {0} calls to Single(predicate) took {1} ms.",
selectors.Length, s.ElapsedMilliseconds);
// Using .Where(predicate).Single()
s = Stopwatch.StartNew();
foreach (int t in selectors) {
s_val = data.Where(x => x == t).Single();
}
s.Stop();
Console.WriteLine(" {0} calls to Where(predicate).Single() took {1} ms.",
selectors.Length, s.ElapsedMilliseconds);
}
public static void Main(string[] args) {
var R = new Random();
var selectors = Enumerable.Range(0, N).Select(_ => R.Next(0, N)).ToArray();
Console.WriteLine("Using IEnumerable<int> (Enumerable.Range())");
DoTest(Enumerable.Range(0, 10 * N), selectors);
Console.WriteLine("Using int[]");
DoTest(Enumerable.Range(0, 10*N).ToArray(), selectors);
Console.WriteLine("Using List<int>");
DoTest(Enumerable.Range(0, 10 * N).ToList(), selectors);
Console.ReadKey();
}
}
Somewhat shockingly, .Where(predicate).Single()
wins by a factor of about two. I even ran both cases twice to make sure caching, etc. was not a factor.
1) 10000 calls to Single(predicate) took 7938 ms.
1) 10000 calls to Where(predicate).Single() took 3795 ms.
2) 10000 calls to Single(predicate) took 8132 ms.
2) 10000 calls to Where(predicate).Single() took 4318 ms.
Updated Results:
Using IEnumerable<int> (Enumerable.Range())
10000 calls to Single(predicate) took 7838 ms.
10000 calls to Where(predicate).Single() took 8104 ms.
Using int[]
10000 calls to Single(predicate) took 8859 ms.
10000 calls to Where(predicate).Single() took 2970 ms.
Using List<int>
10000 calls to Single(predicate) took 9523 ms.
10000 calls to Where(predicate).Single() took 3781 ms.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…