views:

468

answers:

6

Are simple LINQ queries on an IEnumerable<T> lightweight or heavyweight? How do they compare to writing for or foreach loops by hand? Is there a general guideline for when to prefer LINQ versus manual searching?

For example:

var lowNums =
    from n in numbers
    where n < 5
    select n;

Compared to:

List<int> lowNums = new List<int>();

foreach (int n in numbers)
{
    if (n < 5)
    {
        lowNums.Add(n);
    }
}

I was talking to a coworker about LINQ and he expressed some hesitation about using it. He guessed that there might be a lot going on "behind the scenes" in order to support everything LINQ can do.

Is there a significant performance difference between the above examples? Are there any good resources that talk about LINQ performance on collections? A simple Google search for linq performance turned up some seemingly outdated articles.

+7  A: 

There's the overhead of invoking delegates, but that's generally fairly low.

Then there's the overhead of all the iterators involved - usually one iterator per extra clause in the query. Again, not a huge amount, but not nothing either.

Do you have an actual application in mind? If so, how important is the performance in the bit which could be done in LINQ? In my experience these bits are usually not the bottleneck, so if LINQ decreases the performance very slightly it really doesn't matter. LINQ can contribute greatly to the readability of your solution though.

Note that the performance in your example is quite different because the two pieces of code are doing very different things. Your LINQ example will execute in the blink of an eye because it's not actually running the query - it's just setting it up. If you call ToList() at the end then it's basically equivalent to your second example. This sort of thing is very important to remember when doing performance comparisons!

Another thing to bear in mind - you don't have to use the query expression syntax. If you're just filtering (or just projecting) I usually find it makes more sense to call the extension method with normal dot notation:

var lowNums = numbers.Where(n => n < 5);
Jon Skeet
I recently had a whole application built on LINQ to SQL at work...and the old school sql guy attacked all the sql going to the db saying that that linq crap is slow. ORM sucks. All the usual arguments. When he broke out profiler he found that it was actually all of his stored procedures that were slow...and that LINQ performed quite well! I smiled.
Andrew Siemer
The provided example is representative of what I'd be doing: iterate over a simple array to find one or more items which match the specified criteria, such as having a property set to a particular value.
emddudley
@emddudley: But what do you want to do with the results afterwards? LINQ makes it easy to only use them when you want them, without creating a whole list... but that may or may not be more efficient in your case. How many items are there? Do you know you actually have any performance issues?
Jon Skeet
This question was primarily hypothetical. In my application I essentially want to find a single object out of perhaps 10-20, so performance is most certainly not an issue. I just wanted a nice easy way to get a reference to an object in a collection that matches my search criteria.
emddudley
+1  A: 

About the only real performance overhead of LINQ-to-objects over doing it yourself are the few extra objects created to help with the enumeration and the function calls. In short, unless you use it in a way it wasn't designed to, it won't hurt your performance unless you're doing very high-perf stuff.

In that case, I'd implement it the LINQ way first, and let your performance testing tell you in which specific places you may need to consider doing it differently. For quite a bit of code, ease of maintenance trumps pure performance.

Jonathan
+8  A: 

Here is my general rule for LINQ

Use LINQ when the solution is more expressive. Only switch to a less expressive but faster solution when a profiler has proved that the LINQ query is a source of problem.

JaredPar
Excellent advice. Providing that the code in question does not hemorrhage from a performance standpoint, I prefer the more expressive route. Performance tuning, done after the fact, will isolate any areas to be revisited for refactoring. I have yet to have a scenario where LINQ was the problem, rather the surrounding implementations and/or unreasonable assumptions.
joseph.ferris
+12  A: 

The authors of LINQ in Action did some benchmarking with for, foreach, List<T>.FindAll, and LINQ queries that all did the same thing. Depending on how the queries were constructed, LINQ was only about 10% slower. As they put it,

LINQ does not come for free.

LINQ is a complex subject, but depending on what you do with it, it doesn't have to add a lot of overhead. Generally LINQ has been built to rely on deferred execution wherever possible, to save memory and CPU until you actually need it.

However, you have to be aware how the different query operators work, because changing the flow of a query could drastically alter how it's executed. Simple queries as you describe are usually not a problem, but operators like Reverse() and conversion operators can throw some wrenches because they require immediate iteration of the result set. There are often multiple ways to write the same query, and depending on how you construct it, you can be looking at a minimal performance loss or you could make it twice as slow as the equivalent loops.

The convienence and conciseness it offers far outweighs any performance considerations for most of my day to day coding though. Never pre-optimize!

womp
+2  A: 

One great way to convince yourself about LINQ is to use LINQPad. It allows you to output the IL for your LINQ and non-LINQ implementations (as well as output the SQL if you're using LINQ2SQL).

Often times when I have a question about what is exactly happening "behind the scenes" (as your co-worker is wondering), I go to the IL and find out for myself. The vast majority of the time what I've seen is that LINQ's implmenetation is superb.

JP Alioto
+2  A: 

According to LINQ In Action (pg.198):

"LINQ does not come for free. LINQ queries cause additional work, object creations, and pressure on the garbage collector. The additional cost of using LINQ can vary a lot depending on the query. It can be as low as 5 percent, but can sometimes be around 500 percent."

Dan Diplo