Welcome to MSDN Blogs Sign in | Join | Help

Beware of the big bad LINQ

Pop quiz – given:

    Stack<int> stack;

what is the difference between:

    return stack.Count;

and:

    return stack.Count();

Is it:

  1. No difference: both return the number of elements on the specified stack
  2. The first is a property of Stack<T>, while the second is a LINQ extension method
  3. The first uses 3 IL instructions, while the second uses 34
  4. The first runs in constant time, while the second is O(n)
  5. The second version generates garbage, while the first does not

Answer: all of the above.

The extension methods defined in the System.Linq namespace are tremendously powerful, and can be a thing of beauty when used wisely, but with great power comes great responsibility. I find it a more than a little scary that such a subtle code change can have such dramatic performance implications!

Published Thursday, July 16, 2009 7:59 AM by ShawnHargreaves

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

Thursday, July 16, 2009 11:36 AM by onovotny

# Performance fixed in .NET 4.0

In .NET 4.0, the Count() method will check for the ICollection interface in addition to ICollection<T> and use Count on it.  The result will be much faster, as well as being in constant time.

https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=454130

Thursday, July 16, 2009 5:18 PM by Scott Wendt

# re: Beware of the big bad LINQ

This is the sort of thing that a tool like resharper should check for and warn about. Other static analysis could also catch this. I do like seeing the comment about .NET 4.0 fixing this oversite in the libraries theselves though.

I think in general we need to be careful of where the code we are calling is coming from now that extension methods exist. Pre-link the () at the end would have generated a nice compiler error for you. Maybe VS could highlight extension method calls in a different color so that we know they aren't normal class methods or something.

Sorry this is a bit of a ramble just typing as I think :)

Friday, July 17, 2009 8:19 AM by Martin Sherburn

# re: Beware of the big bad LINQ

@Scott: Extension methods do show up with a different icon in the auto-complete list so that you know it's an extension.

I find it quite surprising that Linq is actually available on the Xbox considering that methods like Enum.GetNames haven't been included along with a few other seemingly random things. I use Linq quite a lot for my job and I like it but I wouldn't use it for XNA because of the performance implications.

Friday, July 17, 2009 11:48 AM by TechNeilogy

# re: Beware of the big bad LINQ

I think it comes down to an education thing.  Such features are fine if understood and used appropriately.

This is the kind of thing I've seen happen multiple times in the field.  A dev team goes wild on ease of use features without understanding the consequences of using them in inappropriate or unnecessary situations.  Next thing you know the app bogs down and consumes all the memory on the machine.

-Neil

Friday, July 17, 2009 1:46 PM by Neil

# re: Beware of the big bad LINQ

Speaking of .net 4, I'll be interested to see if dynamic makes it over to Xbox........

Monday, July 20, 2009 8:32 AM by Sean Hederman

# re: Beware of the big bad LINQ

@onovotny: The Count() checks ICollection.Count in .NET 3.5 SP1 as well, making O(1).

@Scott: Extension methods add virtually zero overhead, so I'm not sure why a static analysis should flag them, they're a good practise not a bad one.

@Neil: Actually, since LINQ Count() operates in O(1) time for ICollections, it was implemented 100% fine. If you look at the hot path, they've added 3 IL instructions, hardly a nightmare.

Monday, July 20, 2009 11:45 AM by ShawnHargreaves

# re: Beware of the big bad LINQ

> Extension methods add virtually zero overhead, so I'm not sure why a static analysis should flag them, they're a good practise not a bad one.

Agreed. There's nothing wrong with extension methods per se: it's equally possible to write an instance method that looks innocuous but has surprising perf characteristics!

My point was more about the increasingly high level of abstraction provided by technologies such as LINQ, rather than the fact that these happen to be implemented as extension methods. Increased abstraction is a good thing for all kinds of reasons, but it does make perf less obvious and harder to reason about just from reading code.

Leave a Comment

(required) 
required 
(required) 

  
Enter Code Here: Required
 
Page view tracker