title: LINQ Performance: For vs. LINQ difference gone in C# 6?
body: <p><strong>Edit:</strong> Per DavidG's suggestion, I boosted the number of items by 100x.  I reran the comparison in release mode and updated the results below.  I've also updated the code in case anyone is just copying and pasting and running it locally.</p>
  
  <hr>
  
  <p>So I've seen a lot of posts on SO about LINQ vs. <code>for</code> performance -- most of which are several years old at this point -- and I wanted to see it in action for myself.  So I wrote a small app to test it, and the results were... not quite what I expected.  <strong>My question is: have changes and optimizations in C# 6 made the entire performance issue irrelevant?</strong></p>
  
  <p>(Inasmuch as it was ever an issue instead of an interesting micro-optimization for a large portion of the .NET user base.  Interesting, yes, but not something <em>most</em> people need to really worry about.)</p>
  
  <p>I know there are still good questions about using manual loops vs. LINQ from a memory footprint standpoint, but either my comparison app is badly flawed or it doesn't seem like there's much of a speed difference anymore.  Perhaps it was optimized away in later versions of C#?</p>
  
  <p>My sample app is below.  It's contrived, I admit -- it's a worst-case scenario trying to find an item that will be found dead last in a million-item list -- but I grabbed it based on other posts around here.</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Diagnostics;
  using System.Linq;
  
  namespace LinqDemo
  {
      class Program
      {
          static void Main(string[] args)
          {
              new Program().Run();
          }
  
          public void Run()
          {
              RunPerformanceComparison();
              Console.ReadKey();
          }
  
          private void RunPerformanceComparison()
          {
              Func&lt;string, bool&gt; criteriaFunction = d =&gt; d.Equals("YES");
  
              var data = new string[100000000];
              for (int i = 0; i &lt; data.Length - 1; i++)
              {
                  data[i] = "NO";
              }
  
              data[data.Length - 1] = "YES";
  
  
              Console.WriteLine("With LINQ");
              Console.WriteLine("------------");
              DoPerformanceRunLinq(data, criteriaFunction);
  
              Console.WriteLine();
  
              Console.WriteLine("Without LINQ");
              Console.WriteLine("------------");
              DoPerformanceRunManual(data, criteriaFunction);
          }
  
          private void DoPerformanceRunLinq(string[] data, Func&lt;string, bool&gt; criteriaFunction)
          {
              Stopwatch sw = new Stopwatch();
              for (int i = 0; i &lt; 10; i++)
              {
                  sw.Start();
                  var result = data.Where(criteriaFunction).Select(d =&gt; d).ToList();
                  sw.Stop();
                  Console.WriteLine($"Iteration {i + 1}\tElapsed: {sw.Elapsed.TotalMilliseconds.ToString("n2")} ms");
                  sw.Reset();
              }
          }
  
          private void DoPerformanceRunManual(string[] data, Func&lt;string, bool&gt; criteriaFunction)
          {
              Stopwatch sw = new Stopwatch();
              for (int i = 0; i &lt; 10; i++)
              {
                  sw.Start();
                  var result = GetItems(data, criteriaFunction);
                  sw.Stop();
                  Console.WriteLine($"Iteration {i + 1}\tElapsed: {sw.Elapsed.TotalMilliseconds.ToString("n2")} ms");
                  sw.Reset();
              }
          }
  
          private IEnumerable&lt;string&gt; GetItems(string[] data, Func&lt;string, bool&gt; criteriaFunction)
          {
              var ret = new List&lt;string&gt;();
  
              // Not deferred; runs all at once
              for (int i = 0; i &lt; data.Length; i++)
              {
                  if (criteriaFunction(data[i]))
                  {
                      ret.Add(data[i]);
                  }
              }
  
              return ret;
          }
      }
  }
  </code></pre>
  
  <p>Here's the output from running this (I ran it in the command-line without VS):</p>
  
  <pre>
  With LINQ
  ------------
  Iteration 1     Elapsed: 602.39 ms
  Iteration 2     Elapsed: 522.72 ms
  Iteration 3     Elapsed: 601.15 ms
  Iteration 4     Elapsed: 518.71 ms
  Iteration 5     Elapsed: 511.38 ms
  Iteration 6     Elapsed: 565.92 ms
  Iteration 7     Elapsed: 506.51 ms
  Iteration 8     Elapsed: 524.91 ms
  Iteration 9     Elapsed: 540.85 ms
  Iteration 10    Elapsed: 502.33 ms
  
  Without LINQ
  ------------
  Iteration 1     Elapsed: 496.09 ms
  Iteration 2     Elapsed: 496.15 ms
  Iteration 3     Elapsed: 540.53 ms
  Iteration 4     Elapsed: 549.28 ms
  Iteration 5     Elapsed: 404.46 ms
  Iteration 6     Elapsed: 407.23 ms
  Iteration 7     Elapsed: 461.39 ms
  Iteration 8     Elapsed: 414.90 ms
  Iteration 9     Elapsed: 405.67 ms
  Iteration 10    Elapsed: 437.98 ms
  </pre>
  
  <p>Over 100 <em>million</em> strings, that's better performance on the <code>for</code> side, but not by the significant amounts that some people have claimed in the past (I've heard as much as a 10x difference.  This is not even close.).  Plus, it's 100 million strings in memory -- I don't think the optimization here would be done by choosing manual loops vs LINQ. :)  In fact, I'm not sure the difference here is large enough for <em>anyone</em> to really care, unless you absolutely, positively need every last microsecond of performance.  I'd call it a wash, basically.</p>
  
  <p>Did I screw up my app somewhere, is this just an invalid comparison, or did something change internally to .NET?</p>