166

I am writing a Mesh Rendering manager and thought it would be a good idea to group all of the meshes which use the same shader and then render these while I'm in that shader pass.

I am currently using a foreach loop, but wondered if utilising LINQ might give me a performance increase?

2

8 Answers 8

292

Why should LINQ be faster? It also uses loops internally.

Most of the times, LINQ will be a bit slower because it introduces overhead. Do not use LINQ if you care much about performance. Use LINQ because you want shorter better readable and maintainable code.

9
  • 9
    So your experience is that LINQ is faster and makes code harder to read and to maintain? Please explain.
    – codymanix
    Commented Jun 27, 2011 at 13:51
  • 131
    I think you had it backward. He is saying LINQ is SLOWER. This is due to over head. He is also saying that LINQ is easier to read and maintain. Commented Feb 5, 2013 at 17:18
  • 9
    Sorry. In the meantime we had a lot of things where we compared linq and for or foreach performance, and most of the time linq was faster.
    – Offler
    Commented Oct 30, 2013 at 11:56
  • 60
    To be honest in my opinion, a foreach loop is more readable than its LINQ Method. I use LINQ because it's cool :)
    – LuckyLikey
    Commented May 20, 2015 at 13:19
  • 5
    Yes but in some cases LINQ may really improve readability, so forget my mindless comment <3
    – LuckyLikey
    Commented May 20, 2015 at 13:35
72

LINQ-to-Objects generally is going to add some marginal overheads (multiple iterators, etc). It still has to do the loops, and has delegate invokes, and will generally have to do some extra dereferencing to get at captured variables etc. In most code this will be virtually undetectable, and more than afforded by the simpler to understand code.

With other LINQ providers like LINQ-to-SQL, then since the query can filter at the server it should be much better than a flat foreach, but most likely you wouldn't have done a blanket "select * from foo" anyway, so that isn't necessarily a fair comparison.

Re PLINQ; parallelism may reduce the elapsed time, but the total CPU time will usually increase a little due to the overheads of thread management etc.

1
  • In another answer you alluded to not using LINQ on in-memory collections - e.g. List<Foo>; instead, I should use a foreach block on these collections. The recommendation to use foreach in these contexts does make sense. My concern: should I only replace LINQ queries with foreach if I detect a performance issue? Going forward, I will consider the foreach first.
    – IAbstract
    Commented Apr 26, 2012 at 15:35
27

LINQ is slower now, but it might get faster at some point. The good thing about LINQ is that you don't have to care about how it works. If a new method is thought up that's incredibly fast, the people at Microsoft can implement it without even telling you and your code would be a lot faster.

More importantly though, LINQ is just much easier to read. That should be enough reason.

4
  • 3
    I like the line "Microsoft can implement it" is it possible, I mean is it possible without i upgrading the framework? Commented Oct 15, 2015 at 10:14
  • 4
    LINQ will never really get faster than the native implementation, since at the end of the day, it translates to the native implementation. There are no special LINQ CPU instructions and LINQ registers that can be used to translate faster LINQ machine code - and if there were, they would be used by non-LINQ code too.
    – mg30rg
    Commented Nov 20, 2017 at 10:31
  • No true, at some point certain link operations may become multi-threaded or even utilise the GPU at some point.
    – John Stock
    Commented Apr 5, 2019 at 22:19
  • 2
    Funny foreshadowing from a loong time ago. Nick Chapsas released a video about this yesterday explaining how LINQ now is faster than foreach youtube.com/watch?v=5JKhNV9TY8k
    – fhugas
    Commented Mar 1 at 17:21
20

It should probably be noted that the for loop is faster than the foreach. So for the original post, if you are worried about performance on a critical component like a renderer, use a for loop.

Reference: In .NET, which loop runs faster, 'for' or 'foreach'?

0
12

You might get a performance boost if you use parallel LINQ for multi cores. See Parallel LINQ (PLINQ) (MSDN).

9

I was interested in this question, so I did a test just now. Using .NET Framework 4.5.2 on an Intel(R) Core(TM) i3-2328M CPU @ 2.20GHz, 2200 Mhz, 2 Core(s) with 8GB ram running Microsoft Windows 7 Ultimate.

It looks like LINQ might be faster than for each loop. Here are the results I got:

Exists = True
Time   = 174
Exists = True
Time   = 149

It would be interesting if some of you could copy & paste this code in a console app and test as well. Before testing with an object (Employee) I tried the same test with integers. LINQ was faster there as well.

public class Program
{
    public class Employee
    {
        public int id;
        public string name;
        public string lastname;
        public DateTime dateOfBirth;

        public Employee(int id,string name,string lastname,DateTime dateOfBirth)
        {
            this.id = id;
            this.name = name;
            this.lastname = lastname;
            this.dateOfBirth = dateOfBirth;

        }
    }

    public static void Main() => StartObjTest();

    #region object test

    public static void StartObjTest()
    {
        List<Employee> items = new List<Employee>();

        for (int i = 0; i < 10000000; i++)
        {
            items.Add(new Employee(i,"name" + i,"lastname" + i,DateTime.Today));
        }

        Test3(items, items.Count-100);
        Test4(items, items.Count - 100);

        Console.Read();
    }


    public static void Test3(List<Employee> items, int idToCheck)
    {

        Stopwatch s = new Stopwatch();
        s.Start();

        bool exists = false;
        foreach (var item in items)
        {
            if (item.id == idToCheck)
            {
                exists = true;
                break;
            }
        }

        Console.WriteLine("Exists=" + exists);
        Console.WriteLine("Time=" + s.ElapsedMilliseconds);

    }

    public static void Test4(List<Employee> items, int idToCheck)
    {

        Stopwatch s = new Stopwatch();
        s.Start();

        bool exists = items.Exists(e => e.id == idToCheck);

        Console.WriteLine("Exists=" + exists);
        Console.WriteLine("Time=" + s.ElapsedMilliseconds);

    }

    #endregion


    #region int test
    public static void StartIntTest()
    {
        List<int> items = new List<int>();

        for (int i = 0; i < 10000000; i++)
        {
            items.Add(i);
        }

        Test1(items, -100);
        Test2(items, -100);

        Console.Read();
    }

    public static void Test1(List<int> items,int itemToCheck)
    {

        Stopwatch s = new Stopwatch();
        s.Start();

        bool exists = false;
        foreach (var item in items)
        {
            if (item == itemToCheck)
            {
                exists = true;
                break;
            }
        }

        Console.WriteLine("Exists=" + exists);
        Console.WriteLine("Time=" + s.ElapsedMilliseconds);

    }

    public static void Test2(List<int> items, int itemToCheck)
    {

        Stopwatch s = new Stopwatch();
        s.Start();

        bool exists = items.Contains(itemToCheck);

        Console.WriteLine("Exists=" + exists);
        Console.WriteLine("Time=" + s.ElapsedMilliseconds);

    }

    #endregion

}
5
  • This is what I got: Exists=True Time=274 Exists=True Time=314
    – PmanAce
    Commented Apr 3, 2018 at 21:16
  • 2
    have you considered doing the linq first and foreach later, it might make some difference as well Commented May 14, 2019 at 11:03
  • 4
    Interesting. I got Exists=True Time=184 Exists=True Time=135 It's on an Apache Gaming laptop (Win 10, C# 7.3). Compiled and ran in debug mode. If I reverse the tests I get Exists=True Time=158 Exists=True Time=194. Seems Linq is more optimized I guess. Commented Oct 23, 2019 at 3:31
  • 1
    There is a misunderstanding in this post regarding the object test. While it is definitely interesting that List.Exists and .Contains seem to perform better than the foreach. It's important to note that .Exists is not a linq to entities method and will only work on lists, its linq equivalent method, .Any(), definitely performs slower than the foreach.
    – AbdulG
    Commented Nov 27, 2019 at 10:23
  • 2
    All these inaccurate answers and comments. No, LINQ iterators are not and will never be faster than foreach. Also, List.Exists is not a LINQ method.
    – l33t
    Commented Oct 6, 2020 at 14:48
4

This is actually quite a complex question. Linq makes certain things very easy to do, that if you implement them yourself, you might stumble over (e.g. linq .Except()). This particularly applies to PLinq, and especially to parallel aggregation as implemented by PLinq.

In general, for identical code, linq will be slower, because of the overhead of delegate invocation.

If, however, you are processing a large array of data, and applying relatively simple calculations to the elements, you will get a huge performance increase if:

  1. You use an array to store the data.
  2. You use a for loop to access each element (as opposed to foreach or linq).

    • Note: When benchmarking, please everyone remember - if you use the same array/list for two consecutive tests, the CPU cache will make the second one faster. *
1

Coming in .NET core 7 are some significant updates to LINQ performance of .Min .Max, .Average and .Sum Reference: https://devblogs.microsoft.com/dotnet/performance_improvements_in_net_7/#linq

Here is a benchmark from the post. Benchmark of .NET Core 6 vs 7 LINQ methods

If you compare to a ForEach loop, than it becomes apparent that in .NET 6 the ForEach loop was faster and in .NET 7 the LINQ methods: enter image description here

this was the code of the benchmark using BenchmarkDotNet

using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Running;

public class Program
{
    public static void Main()
    {
        BenchmarkRunner.Run<ForEachVsLinq>();
    }
}

[SimpleJob(RuntimeMoniker.Net60)]
[SimpleJob(RuntimeMoniker.Net70)]
[MemoryDiagnoser(false)]
public class ForEachVsLinq
{
    private int[] _intArray;

    [GlobalSetup]
    public void Setup()
    {
        var random = new Random();
        var randomItems = Enumerable.Range(0, 500).Select(_ => random.Next(999));
        this._intArray = randomItems.ToArray();
    }

    [Benchmark]
    public void ForEachMin()
    {
        var min = int.MaxValue;
        foreach (var i in this._intArray)
        {
            if ( i < min)
                min = i;
        }
        Console.WriteLine(min);
    }

    [Benchmark]
    public void Min()
    {
        var min = this._intArray.Min();
        Console.WriteLine(min);
    }

    [Benchmark]
    public void ForEachMax()
    {
        var max = 0;
        foreach (var i in this._intArray)
        {
            if (i > max)
                max = i;
        }
        Console.WriteLine(max);
    }

    [Benchmark]
    public void Max()
    {
        var max = this._intArray.Max();
        Console.WriteLine(max);
    }


    [Benchmark]
    public void ForEachSum()
    {
        var sum = 0;
        foreach (var i in this._intArray)
        {
            sum += i;
        }
        Console.WriteLine(sum);
    }

    [Benchmark]
    public void Sum()
    {
        var sum = this._intArray.Sum();
        Console.WriteLine(sum);
    }
}

In .NET Core 6 and earlier versions the mentioned methods are slower than doing your own foreach loop and finding the min, max value, average or summarizing the objects in the array.

But in .NET Core 7, the performance increase makes these buildin LINQ methods actually a lot faster. Nick Chapsas shows this in a benchmark video on YouTupe

So if you want to calculate the sum, min, max or average value, you should use the LINQ methods instead of a foreach loop from .NET Core 7 onwards (at least, from a performance point of view)

Edit 2024-03-13

It might also be of interest to take a look at SimdLinq. A 3rd party NuGet package that increases the performance even more than the natural development of .NET can do.

enter image description here

4
  • 5
    "you should use LINQ instead from .NET Core 7 onwards (at least, from a performance point of view)" -- Why? Your info compares LINQ 6.0 vs LINQ 7.0, while the question is about comparing LINQ vs foreach. Not only your comparison is not relevant to the question asked, but also your conclusion is non sequitur. Commented Oct 18, 2022 at 23:01
  • @TheodorZoulias I elaborated my reasoning, hopefully this now makes sense as to why this is relevant to the question at hand. The OP is about Grouping, so it's another method, so my post is not directly an answer to that question, but it is a nuance whether a foreach loop is always faster than LINQ as some of the answers state. Commented Oct 19, 2022 at 17:19
  • Then your answer might be more relevant here: Min() and Max() or single oldschool foreach? But it would still not be a good answer if it contains irrelevant benchmarks. If you can show benchmarks that compare the LINQ method with a manual foreach implementation, then OK. Commented Oct 19, 2022 at 17:36
  • 2
    as requested I added a benchmark; the data was not very heavy, so the differences are not very big, but the result is clear to me Commented Oct 20, 2022 at 18:59

Not the answer you're looking for? Browse other questions tagged or ask your own question.