Saturday, November 26, 2016

LINQ Performance pitfall instead a Pit stop!

I would rather named the title as Linq performance pit stop. Anyway in the interest of time, here is, one of the good examples of how we can start with something very trivial linq query to something convoluted one. Always remember the query in memory or on fly comes with its own pros and cons. One must understand how to use them and when. I took this particular example from pluralsight and thought it to be worth sharing.

Courtesy
https://app.pluralsight.com/library/courses/linq-more-effective/table-of-contents

by Mark Heath.

Slow
var longest=books.First(b => b.Pages==books.Max(a => a.Pages));

Better
var mostBooks= books.Max(a => a.Pages);
var longest=books.First(b => b.Pages == mostBooks);

Best
var longest= books.MaxBy(p => p.Pages);

Hope this useful.

SingleOrDefault() 
Check before using FirstOrDefault
This should be used if query returns single recordset.

var scalarDataSet= result?.Results?.SingleOrDefault();


Linq Data Parallelism
var quotes = quotesForAllProducts();//e.g Get quotes for all products
Parallel.ForEach(products, item => Process(item,quotes));
private void Process(Product item,List<Quote> quotes)       {           var quote= quotes?.SingleOrDefault                   (p =>                       p.Id.Trim().Equals(item.Id ?? string.Empty));           if (quote != null)           {               item.Cost = quote.TotalAmount.GetValueOrDefault();               item.Code = quote.Code;           }                  }

Parrallelism
System.Linq.ParallelEnumerable
Set object values for superset.
Packages = poducts.AsParallel().Select(p => new Package                 {                     tId = p.tId,                     vId = p.vId                 }).ToList(),

SelectMany
private void SetProductsSubSet(IList<Product> products)     {         _products= (IEnumerable<ProductDetail>) products?.AsParallel().SelectMany(a => a.subLevel.Select(p => new ProductDetail         {             Id = a.Id,             Type = a.Type,         })) ?? new List<ProductDetail>();       } 


DefaultIfEmpty() Left Join
public List<Product> AddHospitalAndExtrasProduct()        {            return                 (from A in Main                join B in SubB on A.ID equals B?.Id into MainAndSubB                    from ResultSetA in MainAndSubB.DefaultIfEmpty()                join B in SubC on A.ID equals C?.Id into MainAndSubC                    from ResultSetC in MainAndSubC.DefaultIfEmpty()
            select new Product             {                 Id = Main.Id,                 Name = Main.Name,                 SubBId = ResultSetA != null ? ResultSetA .SubBId : string.Empty,                 SubCId = ResultSetC != null ? ResultSetC .SubCId : string.Empty,             }).ToList();                   }


No comments :