views:

2300

answers:

7

A lot of questions are being answered on stackoverflow, with members specifying how to solve these real world/time problems using lambda expressions.

Are we overusing it, are we considering the performance impact of using lambda expressions?

I found few articles that explores the performance impact of lambda vs anonymous delegates vs for/foreach/loops with different results

  1. Anonymous Delegates vs Lambda Expressions vs Function Calls Performance
  2. Performance of foreach vs. List.ForEach
  3. .Net/C# Loop Performance Test (FOR, FOREACH, LINQ, & Lambda).
  4. DataTable.Select is faster than linq

What should be the evaluation criteria when choosing the appropriate solution? except for the obvious reason that its more concise code and readable when using lambda.

+9  A: 

Code duplication.
If you find yourself writing the same anonymous function more than once, it shouldn't be one.

shoosh
It depends where the code is being duplicated. Say you have to sort a list using the same condition a few times within a method. I'd probably declare a lambda in the method scope and reuse that. But overall, I'd agree with this! +1
Erik van Brakel
Well, not quite. If your types are even remotely complex, specifying the full type of the lambda might be considerably more work than duplicating it a few times.
MichaelGG
That's what 'var' is for. OTOH, if you need to pass or return the lambda as a parameter, then I agree.
Richard Berg
+6  A: 

Well, when we are talking bout delegate usage, there shouldn't be any difference between lambda and anonymous methods : they are the same, just with different syntax. And named methods (used as delegates) are also identical from the runtime's viewpoint. The difference, then, is between using delegates, vs. inline code - i.e.

list.ForEach(s=>s.Foo());
// vs.
foreach(var s in list) { s.Foo(); }

(where I would expect the latter to be quicker)

And equally, if you are talking about anything other than in-memory objects, lambdas are one of your most powerful tools in terms of maintaining type checking (rather than parsing strings all the time).

Certainly, there are cases when a simple foreach with code will be faster than the LINQ version, as there will be fewer invokes to do, and invokes cost a small but measurable time. However, in many cases, the code is simply not the bottleneck, and the simpler code (especially for grouping, etc) is worth a lot more than a few picoseconds.

Note also that in .NET 4.0 (based on the CTP) there are additional Expression nodes for things like loops, commas, etc. I don't think the language supports them (again, based on the public CTP), but the runtime does. I mention this only for completeness: I'm certainly not saying you should use manual Expression construction where foreach would do!

Marc Gravell
SLightly off topic, but I mean to have heard something on the lines of the List.ForEach(. => .. ) to be faster/more efficient/or something than using foreach( .. ) { .. } because it has access to the internal array and doesnt use enumerators and such? may be wrong though...
Svish
It may well have such access, but it needs to do delegate invoke, so double edged. You would need to profile to be sure, but I would expect `foreach` to be marginally quicker.
Marc Gravell
Ironically, that's not the case. Believe it or nor, List.ForEach has the edge. Invocation of a single delegate is quite fast (approaching the same speed as an interface call).
Dustin Campbell
@Dustin - is that comparing against List<T>.Enumerator, or IEnumerator<T>?
Marc Gravell
@marc-gravell: "foreach" will compile using List<T>.Enumerator and List<T>.ForEach is still faster. See: http://diditwith.net/2006/10/05/PerformanceOfForeachVsListForEach.aspxor http://msmvps.com/blogs/jon_skeet/archive/2006/01/20/foreachperf.aspx
Dustin Campbell
Bear in mind that "foreach" essentially calls two methods on each iteration while List<T>.ForEach performs one delegate invocation.
Dustin Campbell
One minor advantage of old-skool anon. methods is that you can omit the argument declarations if you aren't interested in them, whereas lambdas require the right number of args to be declared. button.Click += delegate { Foo(); }; vs. button.Click += (sender, event) => Foo();
Daniel Earwicker
@Earwicker - good point; one I use all the time, so I agree ;-p
Marc Gravell
+3  A: 

I'd say that the performance differences are usually so small (and in the case of loops, obviously, if you look at the results of the 2nd article (btw, Jon Skeet has a similar article here)) that you should almost never choose a solution for performance reasons alone, unless you are writing a piece of software where performance is absolutely the number one non-functional requirement and you really have to do micro-optimalizations.

When to choose what? I guess it depends on the situation but also the person. Just as an example, some people perfer List.Foreach over a normal foreach loop. I personally prefer the latter, as it is usually more readable, but who am I to argue against this?

Razzie
no argument from me either :)
Binoj Antony
+2  A: 

Rules of thumb:

  1. Write your code to be natural and readable.
  2. Avoid code duplications (lambda expressions might require a little extra diligence).
  3. Optimize only when there's a problem, and only with data to back up what that problem actually is.
Dustin Campbell
"Make it correct, make it clear, make it concise, make it fast. In that order" (Wes Dyer http://blogs.msdn.com/wesdyer/archive/2007/03/01/immutability-purity-and-referential-transparency.aspx)
Benjol
A: 

If you need recursion, don't use lambdas, or you'll end up getting very distracted!

Daniel Earwicker
Compare to F#: "let rec y f x = f (y f) x" :)
MichaelGG
+11  A: 

Even though I will focus on point one, I begin by giving my 2 cents on the whole issue of performance. Unless differences are big or usage is intensive, usually I don't bother about microseconds that when added don't amount to any visible difference to the user. I emphasize that I only don't care when considering non-intensive called methods. Where I do have special performance considerations is on the way I design the application itself. I care about caching, about the use of threads, about clever ways to call methods (whether to make several calls or to try to make only one call), whether to pool connections or not, etc., etc. In fact I usually don't focus on raw performance, but on scalibility. I don't care if it runs better by a tiny slice of a nanosecond for a single user, but I care a lot to have the ability to load the system with big amounts of simultaneous users without noticing the impact.

Having said that, here goes my opinion about point 1. I love anonymous methods. They give me great flexibility and code elegance. The other great feature about anonymous methods is that they allow me to directly use local variables from the container method (from a C# perspective, not from an IL perspective, of course). They spare me loads of code oftentimes. When do I use anonymous methods? Evey single time the piece of code I need isn't needed elsewhere. If it is used in two different places, I don't like copy-paste as a reuse technique, so I'll use a plain ol' delegate. So, just like shoosh answered, it isn't good to have code duplication. In theory there are no performance differences as anonyms are C# tricks, not IL stuff.

Most of what I think about anonymous methods applies to lambda expressions, as the latter can be used as a compact syntax to represent anonymous methods. Let's assume the following method:

    public static void DoSomethingMethod(string[] names, Func<string, bool> myExpression)
    {
        Console.WriteLine("Lambda used to represent an anonymous method");
        foreach (var item in names)
        {
            if (myExpression(item))
                Console.WriteLine("Found {0}", item);
        }
    }

It receives an array of strings and for each one of them, it will call the method passed to it. If that method returns true, it will say "Found...". You can call this method the following way:

        string[] names = {"Alice", "Bob", "Charles"};
        DoSomethingMethod(names, delegate(string p) { return p == "Alice"; });

But, you can also call it the following way:

        DoSomethingMethod(names, p => p == "Alice");

There is no difference in IL between the both, being that the one using the Lambda expression is much more readable. Once again, there is no performance impact as these are all C# compiler tricks (not JIT compiler tricks). Just as I didn't feel we are overusing anonymous methods, I don't feel we are overusing Lambda expressions to represent anonymous methods. Of course, the same logic applies to repeated code: Don't do lambdas, use regular delegates. There are other restrictions leading you back to anonymous methods or plain delegates, like out or ref argument passing. The other restriction is that lambdas are meant for simple methods containing one single expression as their body. It also doesn't make sense to create a twisted logic just to make fit several logically independent statements into a single expression just to have them represented as a lambda.

The other nice things about Lambda expressions is that the exact same syntax doesn't need to represent an anonymous method. Lambda expressions can also represent... you guessed, expressions. Take the following example:

    public static void DoSomethingExpression(string[] names, System.Linq.Expressions.Expression<Func<string, bool>> myExpression)
    {
        Console.WriteLine("Lambda used to represent an expression");
        BinaryExpression bExpr = myExpression.Body as BinaryExpression;
        if (bExpr == null)
            return;
        Console.WriteLine("It is a binary expression");
        Console.WriteLine("The node type is {0}", bExpr.NodeType.ToString());
        Console.WriteLine("The left side is {0}", bExpr.Left.NodeType.ToString());
        Console.WriteLine("The right side is {0}", bExpr.Right.NodeType.ToString());
        if (bExpr.Right.NodeType == ExpressionType.Constant)
        {
            ConstantExpression right = (ConstantExpression)bExpr.Right;
            Console.WriteLine("The value of the right side is {0}", right.Value.ToString());
        }
     }

Notice the slightly different signature. The second parameter receives an expression and not a delegate. The way to call this method would be:

    DoSomethingExpression(names, p => p == "Alice");

Which is exactly the same as the call we made when creating an anonymous method with a lambda. The difference here is that we are not creating an anonymous method, but creating an expression tree. It is due to these expression trees that we can then translate lambda expressions to SQL, which is what Linq 2 SQL does, for instance, instead of executing stuff in the engine for each clause like the Where, the Select, etc. The nice thing is that the calling syntax is the same whether you're creating an anonymous method or sending an expression.

Rui Craveiro
+1 All good stuff. One minor correction: the overhead of instantiating invoking and GC-ing an anonymous method is measured in nanoseconds, not microseconds!
Daniel Earwicker
Yeah, of course, thanks!!! lolol
Rui Craveiro
+1  A: 

Any time the lambda simply passes its arguments directly to another function. Don't create a lambda for function application.

Example:

var coll = new ObservableCollection<int>();
myInts.ForEach(x => coll.Add(x))

Is nicer as:

var coll = new ObservableCollection<int>();
myInts.ForEach(coll.Add)

The main exception is where C#'s type inference fails for whatever reason (and there are plenty of times that's true).

MichaelGG