Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which is faster: Single(predicate) or Where(predicate).Single()

Tags:

c#

.net

linq

Discussion resulting from this answer has me curious. Which is faster:

someEnumerable.Single(predicate); 

or

someEnumerable.Where(predicate).Single(); 

After all, the first is shorter, more concise, and seems to be purpose-built.

Even ReSharper suggests the former:

enter image description here

I was arguing in the previous post, that they are functionally identical, and should have very similar runtime.

like image 607
Jonathon Reinhart Avatar asked Jan 17 '14 19:01

Jonathon Reinhart


People also ask

What is single () in C#?

In C#, Single. IsNegativeInfinity(Single) is a Single struct method. This method is used to check whether a specified floating-point value evaluates to negative infinity or not. In some floating point operation, it is possible to obtain a result that is negative infinity.

What is the use of single in Linq?

In LINQ, the Single() method is used to return the single element from the collection, which satisfies the condition. In case, if the Single() method found more than one element in collection or no element in the collection, then it will throw the "InvalidOperationException" error.

Which Linq extension retrieves the first object in a returned list or null if the list is empty?

FirstOrDefault() Returns the first element of a list with any amount of elements, or a default value if the list is empty.


1 Answers

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. 
like image 148
Jonathon Reinhart Avatar answered Oct 01 '22 03:10

Jonathon Reinhart