Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Not sure when to use lambda expressions. Can someone give me examples?

Discussion in 'Scripting' started by anydayzz, Mar 5, 2016.

  1. anydayzz

    anydayzz

    Joined:
    Feb 13, 2016
    Posts:
    111
  2. Teravisor

    Teravisor

    Joined:
    Dec 29, 2014
    Posts:
    654
    With events when you don't want to create separate method for or need to use variables you've declared locally:
    Code (CSharp):
    1. Text text;//Should be set to something
    2. Button button;//Should be set to something
    3. button.onClick.AddListener(()=>text.text = "Something");
    Another common usage is with List.Find, List.Exists and other collections methods that accept Predicate<T>:
    Code (CSharp):
    1. List<GameObject> list; //Should be filled
    2. return list.Exists((GameObject obj)=>obj.name=="Object Name");
    And in general anywhere you need a delegate, but don't want to create another method in class.
     
    Last edited: Mar 5, 2016
    landon912, anydayzz and Kiwasi like this.
  3. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Lambda functions are really useful when you are working with delegates and don't want to, or can't, create a specific method for each delegate.

    The are great for call backs or listeners. It's particuarly relevant when you are looping through a collection.

    Code (CSharp):
    1. Button[] buttons = GetComponentsInChildren<Button>();
    2. for (int i = 0; i < buttons.Length; i++){
    3.     int a = i;
    4.     buttons[i].AddListener (() => {Debug.Log("Button " + a);});
    5. }
    They are also great for creating custom ordering on lists. Say you want to sort a collection by the third letter of a random
    string. You could create a method to do this, but someone later might accidentally use it to sort the list randomly. Or you could create a lambda where you need it. No chance of misuse.
     
    bezier, JiajieXu, Teravisor and 2 others like this.
  4. eisenpony

    eisenpony

    Joined:
    May 8, 2015
    Posts:
    971
    Kasaie, JoeJoe, Mercbaker and 4 others like this.
  5. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Nice call. That thought didn't even cross my mind.
     
    anydayzz likes this.
  6. anydayzz

    anydayzz

    Joined:
    Feb 13, 2016
    Posts:
    111
    Thanks to everyone for your replies.
     
  7. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    Lol.. no lambda expression is a anonymous expression that you use with linq to query a singleton. Its much faster than doing a foreach query. Example if you want to find something in a List or text
     
    Last edited: Mar 7, 2016
    ritesh_khokhani likes this.
  8. Teravisor

    Teravisor

    Joined:
    Dec 29, 2014
    Posts:
    654
    Performance-wise LINQ is epically slow. foreach is slow as well. Nothing is faster than for(...) loop.
    Development-time-wise maybe. But not much.
     
    landon912 likes this.
  9. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    Lol . Who the heck told you that? Compearing ling with single query vs a foreach loop. Is like compearing a car with a rocket. Not much difference?

    while you are. retriving the full list, im retrving only what i want with the => lambda operator. Its a singltone.

    I do love my fast games and complex structues. It makes me happy,:cool:
     
    Last edited: Mar 7, 2016
    dahiyabunty1 likes this.
  10. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
  11. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    From the above picture shows that Lambda expression is multiple times faster than the usual approach, as well it is memory efficient too.
     
  12. Korno

    Korno

    Joined:
    Oct 26, 2014
    Posts:
    518

    I was about to say you had an error in the code due to the way lambda captures and closes over variables in loops but I noticed the local assignment.

    + 1 for the clear example!
     
    landon912, eisenpony and Kiwasi like this.
  13. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    I've been around the block a few times. Now that error only catches me out late at night when I have a deadline. ;)
     
    CDMcGwire and Korno like this.
  14. eisenpony

    eisenpony

    Joined:
    May 8, 2015
    Posts:
    971
    I've never heard the term "anonymous expression" before, is this the same as "anonymous function"? Also, LINQ doesn't only work with singleton's, and I'm not 100% sure what you mean by "query a singleton". Also, be careful not to confuse lambdas with LINQ. It's true that LINQ makes good use of lambdas but a lambda is just a syntax of the C# language, while LINQ is part of the .net framework. They work together nicely but you don't actually need lambdas to use LINQ and you don't need LINQ to use lambdas.

    There is a big flaw in this analysis. The author's distinct implementation uses a List and calls Contains every iteration. The only reason LINQ is outpacing the foreach loop is because its Distinct implementation is much more efficient.

    You might be confusing LINQ generally with something like LINQ2SQL. LINQ works by building an expression tree before evaluating the results. Sometimes, the compiler can optimize that expression tree before evaluating so it might gain speed through an algorithm rewrite. In LINQ2SQL, the expression tree is actually converted into sql and executed on the sql server which can result in a significant speed up in a well designed data model. It can also filter results before they ever leave the sql server, reducing the load on the connecting network and the required memory in the C# process. On it's own, however, LINQ won't magically reduce the number of items you are working with.

    In Unity, LINQ and foreach suffer due to a poor implementation of the Enumeration process, however I believe that flaw only affects the amount of garbage created -- the processing speed is still very good. Despite the leaks, I'm a proponent of using LINQ and foreach in code because they are typically much more expressive, which leads to easier interpretation later. If you find that your game performance is suffering due to a large amount of garbage collection, it may be necessary to go back and change some of your implementation but I would leave that until the optimization phase.

    A for loop might be faster than a foreach loop because of the small amount of state that is required for the state machine, however I think most developers have an inflated idea of how big that advantage is. I think the confusion stems form the fact that we usually use for loops for traversing contiguous data (like an array) while foreach loops are reserved for when you have scattered data, such as in an ordered collection or dictionary.

    In LINQ, there is likely even more overhead because of the need for delegate invokes, so this would be slowest of all for a super simple iteration. However, the power of LINQ is that is creates expression trees first and tries to reduce the complexity of your algorithm before executing. This can lead to some massive speed gains in code that does more than just loop over stuff in memory.

    All this is a fun thought exercise but when it comes to writing code, I strongly recommend you just go with whatever is easiest for you to read. If performance becomes an issue, come back later, read your easy to understand code, and optimize it.
     
    _watcher_, DhiaSendi, bezier and 7 others like this.
  15. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    Not going to answer the part that is bullcrap since it's basically based on very immature trolling. I mix LINQ with Lambda? Where the heck did you get that from? I am clearly not the one who is confused here. Lambda Expressing is not something you only use for SQL. ( you can't even do that with mono,)..., go get some reality check.. They way you talk about optimizing tells me that you are making codes the wrong way..

    Strange i never seen any overhead with my codes running Linq with lambda expression, but i have seen overhead with using foreach (and with even for loops). Maybe my profiler is broken, it must be it..

    Let me ask you something "Pony", since you think you know this well.

    Is this slower ?
    Code (CSharp):
    1. var DbItem = Inventory.items.FirstOrDefault(b => b.ItemID == id);    
    Or even better this?
    Code (CSharp):
    1. var DbItem = Inventory.items.First();    
    Than this?
    Code (CSharp):
    1. foreach (var b in Inventory.items)
    2. {
    3.     if(id == b.ItemID)
    4.      {
    5.      // Find
    6. break;
    7.       }
    8.  
    9. }
    Yes or no? Just to confuse you more, this is not sql. The Dbitem is a script component (base class) that has been allocated on the stack before querying with this expression. Avoiding overhead 100%

    Also how are you going to get the first item without querying all of the others? Linq is useful for more than 1 thing, and all evidence confirms that its most of time faster, and cleaner in memory..

    It doesn't matter that it invokes delegate internally , you don't have to worry about this, you have a much better readable code to work with. Linq change the way the iteration is executed even so both foreach loop and linq query iterates the collection. linq usually comes out faster because of this, and some times allot faster..Not to mention the time you save from not writing spaghetti codes..

    Linq with IEnumerable<T> is pretty useful.. or even IQueryable<T>, it has so many practical applications, going full spaghetti is just waste of time.
     
    Last edited: Mar 7, 2016
  16. Teravisor

    Teravisor

    Joined:
    Dec 29, 2014
    Posts:
    654
    //items.First() is same as items[0], what's to test here? And if you want First(...) from linq you could test it yourself by adding several simple lines to code below. But I think it'll be same as FirstOrDefault as it's just one less command with O(1) complexity which is neglidgeble.

    Let's just write code and test it. Testing on compiled version of course.
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Diagnostics;
    3. using System.Collections.Generic;
    4. using System.Linq;
    5.  
    6. public class Item
    7. {
    8.     public int id;
    9.     public Item(int value){id = value;}
    10. }
    11.  
    12. public class Test : MonoBehaviour {
    13.     void Start () {
    14.         Stopwatch sw = new Stopwatch();
    15.  
    16.         List<Item> items = new List<Item>();
    17.         int count = 1000000;
    18.         for (int a=0;a<count;a++)
    19.             items.Add(new Item(a));
    20.  
    21.         RunTest(items,sw,"Warming up");
    22.  
    23.         for(int a=0;a<50;a++)
    24.         {
    25.             RunTest(items,sw,"Pass "+a);
    26.         }
    27.         Application.Quit();
    28.     }
    29.  
    30.     void RunTest(List<Item> items, Stopwatch watch, string writeString)
    31.     {
    32.         long res1;
    33.         long res2;
    34.         long res3;
    35.         Item foundItem;
    36.         int targetId = Random.Range(0, items.Count);
    37.         watch.Start();
    38.         //First pass without measuring to warmup
    39.         for (int a = 0; a < items.Count; a++)
    40.             if (items[a].id == targetId)
    41.             {
    42.                 foundItem = items[a];
    43.                 break;
    44.             }
    45.         watch.Stop();
    46.         res1 = watch.ElapsedTicks;
    47.         watch.Reset();
    48.         watch.Start();
    49.         foreach (Item item in items)
    50.         {
    51.             if (item.id == targetId)
    52.             {
    53.                 foundItem = item;
    54.                 break;
    55.             }
    56.         }
    57.         watch.Stop();
    58.         res2 = watch.ElapsedTicks;
    59.         watch.Reset();
    60.         watch.Start();
    61.         foundItem = items.FirstOrDefault(b=>b.id == targetId);
    62.         watch.Stop();
    63.         res3 = watch.ElapsedTicks;
    64.         watch.Reset();
    65.         UnityEngine.Debug.Log(writeString+" Element chosen: "+targetId+" for(...): "+res1+" foreach(...): "+res2+" FirstOrDefault(...): "+res3);
    66.     }
    67. }
    68.  
    Warming up Element chosen: 132646 for(...): 7374 foreach(...): 18229 FirstOrDefault(...): 124998
    Pass 0 Element chosen: 767153 for(...): 36747 foreach(...): 82487 FirstOrDefault(...): 699665
    Pass 1 Element chosen: 945489 for(...): 45712 foreach(...): 102181 FirstOrDefault(...): 866045
    Pass 2 Element chosen: 239254 for(...): 11626 foreach(...): 26859 FirstOrDefault(...): 218826
    Pass 3 Element chosen: 154170 for(...): 7378 foreach(...): 16055 FirstOrDefault(...): 140239
    Pass 4 Element chosen: 316147 for(...): 15135 foreach(...): 34351 FirstOrDefault(...): 290884
    Pass 5 Element chosen: 350563 for(...): 17073 foreach(...): 38350 FirstOrDefault(...): 322488
    Pass 6 Element chosen: 80432 for(...): 3853 foreach(...): 8286 FirstOrDefault(...): 72639
    Pass 7 Element chosen: 7741 for(...): 371 foreach(...): 790 FirstOrDefault(...): 7066
    Pass 8 Element chosen: 956794 for(...): 45981 foreach(...): 104802 FirstOrDefault(...): 872657
    Pass 9 Element chosen: 355990 for(...): 18214 foreach(...): 39230 FirstOrDefault(...): 326436
    Pass 10 Element chosen: 663216 for(...): 31967 foreach(...): 71387 FirstOrDefault(...): 603459
    Pass 11 Element chosen: 138291 for(...): 6679 foreach(...): 14345 FirstOrDefault(...): 124449
    Pass 12 Element chosen: 796993 for(...): 38251 foreach(...): 87409 FirstOrDefault(...): 733026
    Pass 13 Element chosen: 215336 for(...): 10465 foreach(...): 24684 FirstOrDefault(...): 199534
    Pass 14 Element chosen: 124493 for(...): 6576 foreach(...): 13027 FirstOrDefault(...): 114028
    Pass 15 Element chosen: 17484 for(...): 853 foreach(...): 1776 FirstOrDefault(...): 16264
    Pass 16 Element chosen: 980660 for(...): 47852 foreach(...): 106800 FirstOrDefault(...): 900802
    Pass 17 Element chosen: 151673 for(...): 7252 foreach(...): 15889 FirstOrDefault(...): 139382
    Pass 18 Element chosen: 149989 for(...): 7141 foreach(...): 15648 FirstOrDefault(...): 135080
    Pass 19 Element chosen: 152121 for(...): 7267 foreach(...): 16204 FirstOrDefault(...): 137974
    Pass 20 Element chosen: 755013 for(...): 36597 foreach(...): 81252 FirstOrDefault(...): 690431
    Pass 21 Element chosen: 95441 for(...): 4588 foreach(...): 9845 FirstOrDefault(...): 85933
    Pass 22 Element chosen: 142326 for(...): 6375 foreach(...): 14854 FirstOrDefault(...): 128176
    Pass 23 Element chosen: 604163 for(...): 28983 foreach(...): 65082 FirstOrDefault(...): 554543
    Pass 24 Element chosen: 800034 for(...): 38745 foreach(...): 89123 FirstOrDefault(...): 733585
    Pass 25 Element chosen: 942483 for(...): 45412 foreach(...): 101624 FirstOrDefault(...): 869230
    Pass 26 Element chosen: 896081 for(...): 43643 foreach(...): 97077 FirstOrDefault(...): 822685
    Pass 27 Element chosen: 687233 for(...): 33269 foreach(...): 74359 FirstOrDefault(...): 628128
    Pass 28 Element chosen: 606687 for(...): 29412 foreach(...): 65470 FirstOrDefault(...): 556654
    Pass 29 Element chosen: 540743 for(...): 26192 foreach(...): 58143 FirstOrDefault(...): 492673
    Pass 30 Element chosen: 65783 for(...): 3173 foreach(...): 6802 FirstOrDefault(...): 59599
    Pass 31 Element chosen: 960928 for(...): 46095 foreach(...): 103416 FirstOrDefault(...): 890523
    Pass 32 Element chosen: 709933 for(...): 34197 foreach(...): 76858 FirstOrDefault(...): 648477
    Pass 33 Element chosen: 780587 for(...): 37588 foreach(...): 83786 FirstOrDefault(...): 709742
    Pass 34 Element chosen: 923218 for(...): 44263 foreach(...): 99252 FirstOrDefault(...): 848679
    Pass 35 Element chosen: 666314 for(...): 32046 foreach(...): 73009 FirstOrDefault(...): 614091
    Pass 36 Element chosen: 910398 for(...): 43853 foreach(...): 97977 FirstOrDefault(...): 833592
    Pass 37 Element chosen: 569084 for(...): 27435 foreach(...): 61522 FirstOrDefault(...): 518975
    Pass 38 Element chosen: 571856 for(...): 29985 foreach(...): 63101 FirstOrDefault(...): 524083
    Pass 39 Element chosen: 509060 for(...): 25375 foreach(...): 55885 FirstOrDefault(...): 467397
    Pass 40 Element chosen: 680563 for(...): 32682 foreach(...): 73874 FirstOrDefault(...): 623217
    Pass 41 Element chosen: 461823 for(...): 22438 foreach(...): 49809 FirstOrDefault(...): 428720
    Pass 42 Element chosen: 601828 for(...): 29638 foreach(...): 66180 FirstOrDefault(...): 549118
    Pass 43 Element chosen: 747782 for(...): 35977 foreach(...): 80466 FirstOrDefault(...): 685284
    Pass 44 Element chosen: 426725 for(...): 20689 foreach(...): 45838 FirstOrDefault(...): 388206
    Pass 45 Element chosen: 779933 for(...): 38185 foreach(...): 83801 FirstOrDefault(...): 711436
    Pass 46 Element chosen: 51940 for(...): 2518 foreach(...): 5294 FirstOrDefault(...): 46774
    Pass 47 Element chosen: 3812 for(...): 170 foreach(...): 391 FirstOrDefault(...): 3426
    Pass 48 Element chosen: 541584 for(...): 26835 foreach(...): 60200 FirstOrDefault(...): 497141
    Pass 49 Element chosen: 683155 for(...): 33052 foreach(...): 73854 FirstOrDefault(...): 627564
    Summary: in List<> case foreach is ~2 times slower than for(...) and FirstOrDefault is from ~5 to ~20 times slower than for(...) depending on element we need to get(higher element number we need to get - higher amount of times). Tests do not include GC.

    Generally, performance difference in this case is neglidgeble, but some more complex LINQ constructs will be much less optimal than writing for loop, you can test it yourself. I've had enough problems with that (and mobile support for LINQ back in time, didn't test it lately) to disrecommend LINQ from my experience.
    You are free to point me to errors in code that could affect test performance or use code to test it on your system/make new tests to see what is better than what. You can exchange List<> for Dictionary<> or HashSet<> or whatever and see how results change(test code change required too obviously). I've done that some time ago, and I'm too lazy to repeat it.

    Generally I agree with @eisenpony, in that it's faster development-time-wise if you know linq. So by all means it's viable.
    With one but: unless you get into mobile troubles or lack of linq knowledge - that's why I disrecommend it for new people.

    P.S. in debug build (in Unity Editor) same test gave me: foreach(...) is 2 times slower than for(...), LINQ is 2 to 6 times slower than for(...).

    EDIT: removed meaningless lines from log.
     
    Last edited: Mar 7, 2016
    DhiaSendi and Dustin-Horne like this.
  17. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    Kinda messy log you had there, the things you add in there "strings etc" probably slow you down more than the iteration it self, and makes the whole thing pretty unreliable, That object would also have pretty big heap size since your allocating inside it. The code i showed as an example, performed very different. It shows that foreach and linq is most of the time equal in speed, but on complex iteration a smart expression will double the performance, just like in link with diagram. Pony even admitted that linq have ability to reduce the execution time when using distinct() . I am not going to force people to use smart codes, your free to make spaghetti codes and disagree with what ever you like. But people should know that there are smart option out there.
     
  18. Teravisor

    Teravisor

    Joined:
    Dec 29, 2014
    Posts:
    654
    I didn't include them in measurement. You should really look at code first. And I haven't seen any GC triggers, so they're not issue.
    That's simple case. Try complex cases yourself, after I've seen them I didn't want to ever use LINQ on mobile systems.
    It does. But raw code that does same is still more efficient in 90% cases. You can counter me with real code that will show me I'm wrong.

    You've stated that LINQ is faster. I disagreed. I never said LINQ is not an option or is bad.
     
    Last edited: Mar 7, 2016
  19. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    well strings are array of chars just like the content in your list. it will allocate but only kick in GC if its needed.. On my test i have like 100ms and pretty stable numbers. The conclusion is clear. Foreach is not faster than Linq query. If people on this forum want to troll go ahead, the facts will still be there. I dont care what people do on there free time.
     
  20. Teravisor

    Teravisor

    Joined:
    Dec 29, 2014
    Posts:
    654
    Post exact numbers and code you've used to get them. I've posted mine and they clearly show that LINQ is slower than foreach. If you're skipping all proof part, that's not discussion. Unless someone proves me wrong, I see no benefit from this topic anymore.
     
    Last edited: Mar 7, 2016
  21. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    Sure. i used your code but did some adjustments.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using System.Linq;
    5.  
    6. public class Item
    7. {
    8.     public int id;
    9.     public Item(int value){id = value;}
    10. }
    11.  
    12. public class Benchmark : MonoBehaviour {
    13.  
    14.     public List<Item> ThisItems;
    15.     Item Linq;
    16.  
    17.     void Awake ()
    18.     {
    19.         ThisItems = new List<Item>();
    20.     }
    21.     void Start ()
    22.     {
    23.         // Populate the list with randome ID
    24.         for (int i = 0; i < 1000; i++)
    25.         {
    26.             ThisItems.Add(new Item(Random.Range(1,100)));
    27.         }
    28.  
    29.         RunTest(55);
    30.     }
    31.          
    32.     void RunTest(int targetId)
    33.     {    
    34.  
    35.         print ("Start");
    36.         print (System.DateTime.Now.Millisecond);
    37.  
    38.         Linq = ThisItems.FirstOrDefault(b=>b.id == targetId);
    39.         if (Linq != null)
    40.         {
    41.             print ("LINQ");
    42.             print (System.DateTime.Now.Millisecond);
    43.         }
    44.  
    45.         for (int a = 0; a < ThisItems.Count; a++)
    46.         {
    47.             if (ThisItems[a].id == targetId)
    48.             {
    49.                 print ("for loop query");
    50.                 print (System.DateTime.Now.Millisecond);
    51.                 break;
    52.             }
    53.         }
    54.  
    55.         foreach (Item item in ThisItems)
    56.         {
    57.             if (item.id == targetId)
    58.             {
    59.                 print ("foreach loop query");
    60.                 print (System.DateTime.Now.Millisecond);
    61.                 break;
    62.             }
    63.         }
    64.  
    65.     }
    66.  
    67.  
    68. }
    69.  

    LINQ : 812ms
    For loop query: 814ms
    Foreach loop query: 814ms

    Do we agree that lower is better?
     
    Last edited: Mar 7, 2016
    Sekretorius and Noxzo like this.
  22. Teravisor

    Teravisor

    Joined:
    Dec 29, 2014
    Posts:
    654
    Nope because lower here means it started earlier in same second and ended earlier in same second, not how much time was consumed.
    Here's what's wrong with that test:
    1. DateTime.Now is current time. In your case it could be that it started at 810 ms, then LINQ took 2 ms (thus 812 ms) then for loop took 2 ms(thus 814 ms) then foreach loop took 0 ms(again 814 ms). That's what I'm seeing (but you didn't output initial time so I have no way to determine it, I'm guessing here). If I would to believe those results, I'd say foreach is fastest of all...
    2. DateTime is much less precise than StopWatch. Those 2 ms could easily be DateTime error. Generally, it might only be useful for testing how much time is spent if your code takes more than several seconds to execute (and even then you take difference between dates, not milliseconds in date).
    3. Your test includes print("") overhead in resulting numbers (which is a lot and you've pointed that out yourself) while mine doesn't.
    4. No pre-warmup. Loop from first attempt might give wrong results (see first entry in log of my tests - it has extremely lower numbers - that's because Unity was still doing something during that run and somehow it ran faster than it should - basically a timing error).
     
    Last edited: Mar 7, 2016
    bezier and landon912 like this.
  23. landon912

    landon912

    Joined:
    Nov 8, 2011
    Posts:
    1,579
    Not sure if serious or just now trolling in an attempt to fool someone.
     
    Deleted User, Kiwasi and Teravisor like this.
  24. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    lol you are really confused with overhead and allocation its not the same thing. Its shows the ms between them, and clearly there is no much difference.. that again concludes that foreach or for loop is not faster

    i forgot to copy this at the start..

    Code (CSharp):
    1.         print ("Start");
    2.         print (System.DateTime.Now.Millisecond);
    Then you can just do the simple math
     
  25. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    No its simple math.

    Start time 881ms + 883 = 2 ms

    883ms + 886ms = 3 ms
    886ms + 888ms = 2 ms
     
  26. Teravisor

    Teravisor

    Joined:
    Dec 29, 2014
    Posts:
    654
    You do print("") before taking new time. I bet it takes 2-3 ms by its own. So what are you testing?

    Yeah, simple:
    for(...) loop is 2 ms while foreach(...) is 0 ms. That just proves it's incorrect at its root as nothing can be faster than for(...) loop.
    btw, in my test LINQ took 5 ms while for(...) and foreach(...) took 1 ms each. So what now? It just proves it's extremely unreliable. While results I've posted were consistent on 50 tries (relatively to each other with different position in array to find).

    I'm sorry, but I'll disregard you as troll and leave this discussion because I agree with
     
    bezier likes this.
  27. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    the difference is the same even with Debug.Log, Output will always be string. Don't know who is the troll here..
     
  28. Teravisor

    Teravisor

    Joined:
    Dec 29, 2014
    Posts:
    654
    I'm calling StopWatch.Stop before calling Debug.Log so Debug.Log doesn't influence result even one tick. Please, learn what StopWatch is and read my code exactly how it is before saying such things.
     
    landon912 and Dustin-Horne like this.
  29. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    well your welcome to put in your stop watch if you think it will make any difference. I just made a quick demonstration to show that the difference is almost zero on normal iteration. Any thing less than 1 ms is unnoticeable.
     
  30. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    11,022
    Soo...

    LINQ took somewhere between 0 to 812ms
    For loop took ~2ms
    Foreach loop took ~0ms

    Which uhhhh...

    Okay?
     
    _watcher_, passerbycmc and Teravisor like this.
  31. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    11,022
    Also, even with the way you interpret your results:
    Which... That's not math. But that's not the issue.

    Here's how you know you are wrong, even if you don't look at your code. I honestly don't know about LINQ, but there is no way Foreach is faster than a for loop.
     
  32. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    >Start time 881ms<

    881ms + 883 = 2 ms LINQ
    883ms + 886ms = 3 ms For loop (i am pretty sure its 2)
    886ms + 888ms = 2 ms Foreach loop

    Conclusion no significant difference
     
  33. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    if you think its wrong, put in your own measure instead saying i am wrong.
     
  34. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    the speed really comes down to what you are iterating, in this case its int (witch is fast) hence no difference from foreach and for loop, i totally agree that for loop is faster then foreach, but linq is not slower, every thing in this thread here prove this.

    There's clearly no lagg or GC happening because of the use of linq..
     
    Noxzo likes this.
  35. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    11,022
    Nothing, literally nothing in this thread proves that LINQ is faster.

    You have to be a troll, there is no other explanation.

    Please look forward to my own benchmarks where instead I'll use DateTime.Now.Day ... The results may surprise you!
     
    BenZed and Teravisor like this.
  36. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    Ignores you trolling. If you had some grasp you should know that DateTime.Now.Millisecond has precision... Trolling is very annoying and immature, DateTime.Now.Days have nothing to do with this.

    Stopwatch is not more accurate than DateTime.Now.Millisecond.
     
    Last edited: Mar 7, 2016
    Noxzo likes this.
  37. BenZed

    BenZed

    Joined:
    May 29, 2014
    Posts:
    524
    Just report @Ironmax and move on, guys. He's just a troll.
     
    ScottJak, Develax, _watcher_ and 3 others like this.
  38. Noxzo

    Noxzo

    Joined:
    Feb 16, 2014
    Posts:
    14
    Do you report some one just because you disagree? Pretty hars.

    From what I can see he provided evidence that Linq is not slower to use. How this is trolling i wonder.
     
    Last edited: Mar 7, 2016
  39. ericbegue

    ericbegue

    Joined:
    May 31, 2013
    Posts:
    1,353
    :) Sorry, I'm not really following the discussion. But that "simple math" stroke me hard.
     
  40. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    This is the easiest argument in history to settle. Microsoft has provided the reference source code for .NET and in fact it's impossible for LINQ's FirstOrDefault method to be faster than for or foreach... let me tell you why. Because it acutally calls foreach!

    http://referencesource.microsoft.co...inq/Enumerable.cs,b7e5965cab68b1cf,references

    Source code for the IEnumerable FirstOrDefault<TSource> extension method.
    Code (csharp):
    1.  
    2. public static TSource FirstOrDefault<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) {
    3.   if (source == null) throw Error.ArgumentNull("source");
    4.   if (predicate == null) throw Error.ArgumentNull("predicate");
    5.   foreach (TSource element in source) {
    6.   if (predicate(element)) return element;
    7.   }
    8.   return default(TSource);
    9.   }
    10.  
     
    landon912, MV10 and Kiwasi like this.
  41. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    That will fail when you use some of the linq functions like distinct(), i already said that they are both iterating the collection equal , its when it comes to execution you see the difference. Fast also means readability and accessibility. Using linq is not slower..



    If you worry about memory use, you can implemented a caching for delegates.

    You can implement Linq wrong
    and get bad performance, sure, but you can also do it right and gain performance.
     
  42. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    You're losing me... so first you claim that iterating with LINQ is faster than for or foreach... which I just showed exactly why it can't possibly be... and your argument to it is now to show delegate specific performance results?
     
  43. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    Sorry? where did i say iterating the collection is faster with Linq? I said the execution can be faster. Both foreach and linq uses IEnumerable<T> (iterating a collection) Linq is more than that.. I hope we can move the discussion further from that point, else i see no point explaining this further.
     
  44. eisenpony

    eisenpony

    Joined:
    May 8, 2015
    Posts:
    971
    I can hardly believe I'm taking the bait on this ..

    The problem isn't with disagreeing or showing alternative evidence, we want to encourage that. The issue is these kinds of responses:

    There was nothing in my post personally attacking IronMax. I was simply pointing something out which I thought could be confusing based on the way he worded something. I'm not trying to tell IronMax he is wrong, I'm trying to make something clear for other readers. In fact, the only person I'm really trying to help out is the OP since he had a legitimate question.

    Instead of agreeing that, yes lambdas are not necessarily tied to LINQ, IronMax immediately gets defensive assuming I'm calling him out. Then, starts the name calling.. I think we can provide alternative viewpoints and suggestions to the OP without resorting to "my way is 100% correct and anyone that disagrees with me obviously has no idea how to code".

    IronMax, if you have a problem with the way something was phrased, please point that out rather than rant about my inability to program.

    Also, there really is something wrong with the analysis done here. http://www.c-sharpcorner.com/uploadfile/40e97e/speed-of-lambda/

    In fact, if you read the first comment and the authors reply, you'll see that author actually admits his comparison is unfair.
     
  45. eisenpony

    eisenpony

    Joined:
    May 8, 2015
    Posts:
    971
    This is true. It is the unique power of LINQ. It creates expression trees before execution. These trees can be optimized in certain cases such as completing two operations during a single iteration. Point-in-case, a Distinct combined with Sum can be flattened into a single loop rather than building a distinct collection followed by a second iteration to complete the sum.

    These are the kinds of complex things LINQ excels at that we can't measure doing simple looping tests.
     
    Ironmax likes this.
  46. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    7,384
    Well this was amusing.
     
  47. eisenpony

    eisenpony

    Joined:
    May 8, 2015
    Posts:
    971
    Yes, if there's one thing we can rely on IronMax for, it's to get the community "engaged" ...
     
  48. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    And last time (months ago) that I engaged him on a topic he took a snippet of one of my statements, completely out of context, and put it in his forum signature attributed to me in an effort to make me look stupid. It certainly doesn't add any value to the discusstion.

    Now, to the OPs post. Lambdas are cool, and powerful. I don't know that there's any magical answer on when to use them. You can use them with Linq, or other places to make your code more readable and clean. They don't generally yield better performance, but sometimes the impact is minimal and the tradeoff is worthwhile.

    You can also use them in method calls. You can create your own methods that take Func<T> for example, and use lambdas when calling your methods. This gives you the capability of adding callbacks to your methods, or doing some custom processing. There are a lot of good uses, but in many cases it's just syntactic sugar.
     
    Kiwasi likes this.
  49. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Generous use of the ignore button is advised. ;)
     
    BenZed and Ryiah like this.
  50. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    Did you miss my signature? I did the same thing with hippocoder , sorry if that offended you, it was only meant as a harmless joke, and i did remove it on your request, come to think of it, i still thinks its pretty funny :). I understand that trolling and personal attacking is allowed on this forum. but when you do, don't come crying when you taste your own medicine. Your where really not that innocent yourself in that thread ...

    For does you know me, know that i am a pretty friendly guy, i have no intention to troll any one or any subject, if i offended any one for no reason on this thread i deeply apologies, but i hope that people with other "views" can be respected without being trolled at or threaten with reports (because that is pretty immature).

    If i came out to hars, then i am sorry about that, i take it in to consideration next time. I am just defending Linq + Lambda Expression as a usable application with Unity nothing more.
     
    Last edited: Mar 7, 2016