Which linq method performs better: Where(expression).FirstorDefault() vs .FirstOrDefault(expression)
Introduction
When it comes to LINQ, we always have multiple options to execute the query for the same scenario. Choosing correct one is always challenging aspect and debatable one. In one of our previous articles Any Vs Count , we have done performance testing about best LINQ methods over .NET types. In this article, I would like to share about Where(expression).FirstorDefault() vs .FirstOrDefault(expression)
Approaches
Performance testing for Where(expression).FirstorDefault() vs .FirstOrDefault(expression) is very interesting
- IEnumerable<T> or ICollcetion<T> .FirstOrDefault(expression) is better than Where(expression).FirstorDefault()
Public API
To check the performance, I need some amount of data which should already available. So I decided to choose this public api. Thanks to publicapis
Public API Models
Entry class
using System; using System.Collections.Generic; using System.Text; namespace AnyVsCount { public class Entry { public string API { get; set; } public string Description { get; set; } public string Auth { get; set; } public bool HTTPS { get; set; } public string Cors { get; set; } public string Link { get; set; } public string Category { get; set; } } }
Root Collection
using System; using System.Collections.Generic; using System.Text; namespace AnyVsCount { public class RootCollection { public int count { get; set; } public ICollection<Entry> entries { get; set; } } }
Root Enumerable
using System; using System.Collections.Generic; using System.Text; namespace WhereVsFirstORDefault { public class RootEnumerable { public int count { get; set; } public IEnumerable<Entry> entries { get; set; } } }
IEnumerable<T> .FirstOrDefault(expression) is better than Where(expression).FirstorDefault()
Tick Count Based Approach IEnumerable<T>
For Where(Expression).FirstOrDefault() vs .FirstOrDefault(Expression) method comparisons we will evaluate based on tick counts in executing the LINQ Statement.
using Newtonsoft.Json; using System; using System.Linq; using System.Net.Http; using System.Threading.Tasks; namespace WhereVsFirstORDefault { class Program { static async Task Main(string[] args) { Console.WriteLine("Who is better performer Where(expression).FirstorDefault() vs .FirstOrDefault(expression)(IEnumerable<T>)?"); var client = new HttpClient(); var response = await client.GetAsync("https://api.publicapis.org/entries"); if (response.IsSuccessStatusCode) { var data = await response.Content.ReadAsStringAsync(); var coll = JsonConvert.DeserializeObject<RootEnumerable>(data); //AdoptAPet Console.WriteLine("Evaluating Where(expression).FirstorDefault() Method:"); Console.WriteLine("-----------------------"); var watch1 = System.Diagnostics.Stopwatch.StartNew(); // the code that you want to measure comes here var result1 = coll.entries.Where(x=>x.API.ToLower() == "AdoptAPet").FirstOrDefault(); watch1.Stop(); var elapsedMs1 = watch1.ElapsedTicks; Console.WriteLine("IEnumerable<T>.Where(expression).FirstorDefault() : " + elapsedMs1 + " Ticks"); Console.WriteLine("-----------------------"); Console.WriteLine(" "); Console.WriteLine("Evaluating FirstOrDefault(expression) Method:"); Console.WriteLine("-----------------------"); var watch2 = System.Diagnostics.Stopwatch.StartNew(); // the code that you want to measure comes here var result2 = coll.entries.FirstOrDefault(x => x.API.ToLower() == "AdoptAPet"); watch2.Stop(); var elapsedMs2 = watch2.ElapsedTicks; Console.WriteLine("IEnumerable<T>.FirstOrDefault(expression) : " + elapsedMs2 + " Ticks"); Console.WriteLine("-----------------------"); Console.ReadKey(); } } } }
Debug Video IEnumerable<T>
IEnumerable<T> Performance Result
Why IEnumerable<T>.FirstOrDefault(expression) is better performer than IEnumerable<T>.Where(Expression).FirstOrDefault()
FirstOrDefault(expression) will find for an item and stop its execution immediately when its found the element or item. In other case, Where(Expression).FirstOrDefault() will run first scan in identifying the item and then it will do additional scan to pick the element from the result of first scan. That's why .FirstOrDefault(Expression) is better than Where(Expression).FirstOrDefault().
Let's try ICollection<T>
ICollection<T> .FirstOrDefault(expression) is better than Where(expression).FirstorDefault()
using Newtonsoft.Json; using System; using System.Linq; using System.Net.Http; using System.Threading.Tasks; namespace WhereVsFirstORDefault { class Program { static async Task Main(string[] args) { Console.WriteLine("Who is better performer Where(expression).FirstorDefault() vs .FirstOrDefault(expression)(ICollection<T>)?"); var client = new HttpClient(); var response = await client.GetAsync("https://api.publicapis.org/entries"); if (response.IsSuccessStatusCode) { var data = await response.Content.ReadAsStringAsync(); var coll = JsonConvert.DeserializeObject<RootCollection>(data); //AdoptAPet Console.WriteLine("Evaluating Where(expression).FirstorDefault() Method:"); Console.WriteLine("-----------------------"); var watch1 = System.Diagnostics.Stopwatch.StartNew(); // the code that you want to measure comes here var result1 = coll.entries.Where(x=>x.API.ToLower() == "AdoptAPet").FirstOrDefault(); watch1.Stop(); var elapsedMs1 = watch1.ElapsedTicks; Console.WriteLine("ICollection<T>.Where(expression).FirstorDefault() : " + elapsedMs1 + " Ticks"); Console.WriteLine("-----------------------"); Console.WriteLine(" "); Console.WriteLine("Evaluating FirstOrDefault(expression) Method:"); Console.WriteLine("-----------------------"); var watch2 = System.Diagnostics.Stopwatch.StartNew(); // the code that you want to measure comes here var result2 = coll.entries.FirstOrDefault(x => x.API.ToLower() == "AdoptAPet"); watch2.Stop(); var elapsedMs2 = watch2.ElapsedTicks; Console.WriteLine("ICollection<T>.FirstOrDefault(expression) : " + elapsedMs2 + " Ticks"); Console.WriteLine("-----------------------"); Console.ReadKey(); } } } }
Debug Video ICollection<T>
ICollection<T> Performance Result
For both IEnumerable and ICollection types .FirstOrDefault(expression) is better performer than .Where(expression).FirstOrDefault(). Hope you like this article
Comments
Post a Comment