Alex Rivera | Logout

Performance concern when using LINQ "everywhere"?

Asked 2010-04-20T11:24:21.617
19

After upgrading to ReSharper5 it gives me even more useful tips on code improvements. One I see everywhere now is a tip to replace foreach-statements with LINQ queries. Take this example:

private Ninja FindNinjaById(int ninjaId)
{
    foreach (var ninja in Ninjas)
    {
        if (ninja.Id == ninjaId)
            return ninja;
    }
    return null;
}

This is suggested replaced with the following using LINQ:

private Ninja FindNinjaById(int ninjaId)
{
    return Ninjas.FirstOrDefault(ninja => ninja.Id == ninjaId);
}

This looks all fine, and I'm sure it's no problem regarding performance to replace this one foreach. But is it something I should do in general? Or might I run into performance problems with all these LINQ queries everywhere?

Edit
Report

1 Answer

8

One thing we identified to be performance problematic is creating lots of lambdas and iterating over small collections. What happens in the converted sample?

Ninjas.FirstOrDefault(ninja => ninja.Id == ninjaId)

First, new instance of (generated) closure type is created. New instance in managed heap, some work for GC. Second, new delegate instance is created from method in that closure. Then method FirstOrDefault is called. What it does? It iterates collection (same as your original code) and calls delegate.

So basically, you have 4 things added here: 1. Create closure 2. Create delegate 3. Call through delegate 4. Collect closure and delegate

If you call FindNinjaById lots of times, you will add this to may be important perforamnce hit. Of course, measure it.

If you replace it with (equivalent)

Ninjas.Where(ninja => ninja.Id == ninjaId).FirstOrDefault()

it adds 5. Creating state machine for iterator ("Where" is yielding function)

answered 2010-04-20T12:33:49.090

Your Answer