Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

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
15,053 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));
          }
        }
    }
}