C# Querying With LINQ Querying the BirdWatcher Data Which is Faster? Union versus Concat

Elshad Shabanov
Elshad Shabanov
2,890 Points

In my test, Concat + Distinct is way faster than Concat alone or Union

In Linq chapter - Which is Faster? Union or Concat, I've got different results. Here is my code:

        //
        var listA = Enumerable.Range(0, 100000);
        var listB = Enumerable.Range(50000, 100000);

        Stopwatch stopWatch = new Stopwatch();

        //Union operation
        stopWatch.Start();
        var listUni = listA.Union(listB);
        stopWatch.Stop();
        var unionTicks = stopWatch.ElapsedTicks;

        //Concat operation
        stopWatch.Restart();
        var listCon = listA.Concat(listB);
        stopWatch.Stop();
        var concatTicks = stopWatch.ElapsedTicks;

        //Concat and Distinct operations
        stopWatch.Restart();
        var listConDist = listA.Concat(listB).Distinct();
        stopWatch.Stop();
        var conDisTicks = stopWatch.ElapsedTicks;

        Console.WriteLine($"Union: {unionTicks}");
        Console.WriteLine($"Concat: {concatTicks}");
        Console.WriteLine($"ConDist: {conDisTicks}");

        /* output:
            Union: 3049
            Concat: 1076
            ConDist: 37
         */

2 Answers

James Churchill
STAFF
James Churchill
Treehouse Teacher

Elshad,

Great catch! Thanks for taking the time to report this issue.

There's something else also at play here; both in your code example and the example that's shown in the video. What execution times do you get if you add to the end of your queries a call to either the ToList or Count method?

Here's an example using the Count method:

var listA = Enumerable.Range(0, 100000);
var listB = Enumerable.Range(50000, 100000);

Stopwatch stopWatch = new Stopwatch();

// Union operation
stopWatch.Start();
var listUniCount = listA.Union(listB).Count();
Console.WriteLine(listUniCount);
stopWatch.Stop();
var unionTicks = stopWatch.ElapsedTicks;

// Concat operation
stopWatch.Restart();
var listConCount = listA.Concat(listB).Count();
Console.WriteLine(listConCount);
stopWatch.Stop();
var concatTicks = stopWatch.ElapsedTicks;

// Concat and Distinct operations
stopWatch.Restart();
var listConDistCount = listA.Concat(listB).Distinct().Count();
Console.WriteLine(listConDistCount);
stopWatch.Stop();
var conDisTicks = stopWatch.ElapsedTicks;

Console.WriteLine($"Union: {unionTicks}");
Console.WriteLine($"Concat: {concatTicks}");
Console.WriteLine($"ConDist: {conDisTicks}");

You should notice substantially longer execution times. Why is that? Well, without calling a method like ToList or Count that requires the query to be enumerated in order to return a result, LINQ queries won't be enumerated until absolutely necessary. This is called "deferred execution".

For more information, see: https://msdn.microsoft.com/en-us/library/bb738633(v=vs.110).aspx

Back to your original point though: even with the longer execution times, Concat+Distinct is considerably faster than Union. We're working on a fix to the course, so we hope to have this issue resolved sometime soon.

Thanks ~James

Kevin Gates
Kevin Gates
13,160 Points

Mine shows Union faster by 381 ticks, but I'm not showing the same code you have above.

Mine is:

using System;
using System.Diagnostics;
using System.Linq;

namespace UnionVsConcat
{
    class Program
    {
        public static void Main(string[] args)
        {
          var listA = Enumerable.Range(0,100000);
          var listB = Enumerable.Range(50000, 100000);

          Stopwatch stopwatch = new Stopwatch();
          stopwatch.Start();
          var listC = listA.Union(listB);
          stopwatch.Stop();
          var unionTicks = stopwatch.ElapsedTicks;

          stopwatch.Restart();
          var listD = listA.Concat(listB).Distinct();
          stopwatch.Stop();
          var concatTicks = stopwatch.ElapsedTicks;

          Console.WriteLine(string.Format("Union took {0} ticks", unionTicks));
          Console.WriteLine(string.Format("Concat took {0} ticks", concatTicks));

          if ( unionTicks > concatTicks)
          {
            Console.WriteLine("Concat is faster by {0}", (unionTicks - concatTicks));
          }
          else if ( concatTicks > unionTicks)
          {
            Console.WriteLine("Union is faster by {0}", (concatTicks - unionTicks));
          }
        }
    }
}