6

I did a small experiment to test whether lamdba expression can retrieve faster results than foreach statement. but, Lambda failed

System.Diagnostics.Stopwatch st = new System.Diagnostics.Stopwatch();
        st.Start();
        List<int> lst = new List<int>();
        foreach (GridViewRow item in GridView1.Rows)
        {
            if (((CheckBox)item.FindControl("Check")).Checked)
            {
                lst.Add(Convert.ToInt32(((Label)item.FindControl("Id")).Text));
            }
        }
        st.Stop();
        Response.Write(st.Elapsed.ToString());
        Response.Write("<br/><br/><br/>");
        st.Reset();
        st.Start();
        List<int> lstRank = GridView1.Rows.OfType<GridViewRow>().Where(s => ((CheckBox)s.FindControl("Check")).Checked)
                                                                     .Select(s => Convert.ToInt32(((Label)s.FindControl("Id")).Text)).ToList();
        st.Stop();
        Response.Write(st.Elapsed.ToString());
        int i = 0;


output
00:00:00.0000249


00:00:00.0002464 

why lambda is slower than foreach. This may be a drawback of lambda expression

Ulhas Tuscano
  • 5,502
  • 14
  • 58
  • 89
  • You can have a look here: http://stackoverflow.com/questions/672918/when-not-to-use-lambda-expressions and here http://stackoverflow.com/questions/1182922/what-is-the-efficiency-and-performance-of-linq-and-lambda-expression-in-net – Adrian Fâciu Mar 23 '11 at 09:13
  • 5
    Your benchmark isn't running for *nearly* enough time to be really meaningful. I don't trust benchmarks that measure for less than a few seconds. – Jon Skeet Mar 23 '11 at 09:15

3 Answers3

3

Technically your 2 approaches are not identical. There are a few differences such as the use of "OfType" which is filtering the collection before continuing. You'd be better using "Cast<GridViewRow>()" as you know each element is of type GridViewRow.

Also, do you really need the expense of the ToList() at the end of the Linq statement as your linq query is now ready to iterate over and execute rather than having to convert back to a list?

Brian Scott
  • 9,221
  • 6
  • 47
  • 68
  • True - if `GridView1.Rows` contained something that wasn't derived from `GridViewRow`, the `foreach` version would throw a type exception. – Daniel Earwicker Mar 23 '11 at 09:33
2

There is a small overhead with lambda expressions because they are "compiled" at runtime. I think that's what you see in your "benchmark". for each ... is a fully compiled statement.

You can precompile lambda expressions. Look here. Maybe you want to rework your code and test again.

Community
  • 1
  • 1
Dirk Brockhaus
  • 4,922
  • 3
  • 38
  • 47
  • No, that's not happening here. These are ordinary lambdas, not expression trees. – Daniel Earwicker Mar 23 '11 at 09:34
  • @Daniel: A dumb question and a little OT: Are ordinary lambas completely compiled? Can ‘t find a link stating this. Can you help? – Dirk Brockhaus Mar 23 '11 at 09:52
  • 3
    for an ordinary lambda, imagine the compiler just moving your code out into a separate method and inventing a name for it. In fact you don't need to imagine it: if you use ILDASM or Reflector to look at the generated code, you can find out the compiler-generated name. If the lambda captures ("closes over") a local variable from the enclosing method, that variable becomes a field of a compiler-generated class, and an object of that class is allocated by the outer method so the variable can be shared. So no special interpreting/compiling has to be done at runtime. – Daniel Earwicker Mar 23 '11 at 10:07
  • @Daniel: Many thanks for this detailed and skilled explanation. I'm sorry - the way I asked you - there is no reputation coming with this. – Dirk Brockhaus Mar 23 '11 at 10:16
2

I won't talk about the correctness of your code but I'd like to get a chance to explain a general rule In Software Develpment the performance loss is inversely proportional to the level of abtsraction. In this case in quite normal that foreach is faster then LINQ (which is more abstract). If you compare it with the classic for (for (int i:i++l,etc..) ) it will be faster than the foreach. Access an object thought an interface is slower then access the concrete object : the interface is already a very small level of abstraction. The code you write will be as much fast as it is "close" to the machine language but of course it will be less readable and maintainable. The matter is how to find the right level of abstraction for what we are developing keeping an eyes on the performance and the code readability.

You won't need MVC pattern for making a one-page web site that shows a table on a Repeater :-)

Massimiliano Peluso
  • 26,379
  • 6
  • 61
  • 70