There are multiple benchmarking results already out there for LINQ. The reason why I am doing this again is the because I have heard multiple times that the latest version of LINQ contains a lot of improvements.
My current configuration is...
Windows Server 2008 Enterprise SP 1
Visual Studio 2008 SP1
4GB RAM
System.Core version 3.5.30729.1
In this post, I will take a look at the results ONLY from LINQ to Collection (An array of strings). You can play around with the code and post other findings (in comments) if any.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace EventAndDelegateDemo
{
class LINQPerf
{
static string[] strArray;
static string[] strFetch;
private const int number = 10; //Change this number to make the Array larger
public static void Main()
{
FillTheArrayWithGUID();
FetchSixElements();
Console.WriteLine("Using For Each loop");
UseForEachLoop();
Console.WriteLine("\n\n");
Console.WriteLine("Using LINQ");
UseLINQ();
}
private static void UseForEachLoop()
{
Stopwatch sw = new Stopwatch();
for (int i = 0; i < 6; i++)
{
sw.Start();
foreach (var item in strArray)
{
if (item == strFetch[i])
{
Console.Write("Guid = {0}", item);
sw.Stop();
Console.Write(" Item was found in {0} ticks\n", sw.ElapsedTicks.ToString());
break;
}
}
}
}
private static void UseLINQ()
{
Stopwatch sw = new Stopwatch();
for (int i = 0; i < 6; i++)
{
sw.Start();
var qry = from x in strArray
where x == strFetch[i]
select x;
foreach (var item in qry)
{
Console.Write("Guid = {0}", item);
}
sw.Stop();
Console.Write(" Item was found in {0} ticks\n", sw.ElapsedTicks.ToString());
}
}
#region Initialize the Array and fetch 6 elements for comparison
private static void FillTheArrayWithGUID()
{
//Fill the string Array with GUIDs
strArray = new string[number * 6];
for (int i = 0; i < number * 6; i++)
{
strArray[i] = System.Guid.NewGuid().ToString();
}
}
private static void FetchSixElements()
{
//Fetch just 6 elements from the big array for comparison
//We are fetching the elements from different locations to see if that has any affect on performance
strFetch = new string[6];
strFetch[0] = strArray[0 * number];
strFetch[1] = strArray[1 * number];
strFetch[2] = strArray[2 * number];
strFetch[3] = strArray[3 * number];
strFetch[4] = strArray[4 * number];
strFetch[5] = strArray[5 * number];
}
#endregion
}
}
Results with private const int number = 10
Results with private const int number = 1000000
If you do the maths, you will find that with an array of 60 strings...
| To find nth element... |
LINQ took... (M) |
For Loop took... (N) |
M/N |
| 0 |
4292 |
768 |
5.58 |
| 50 |
7195 |
3552 |
2.02 |
And for the array of 6 million strings...
| To find nth element... |
LINQ took... (M) |
For Loop took... (N) |
M/N |
| 0 |
2352237 |
826 |
2847!!!! |
| 1000000 |
4607527 |
359450 |
12.81!! |
| 5000000 |
13586926 |
5322037 |
2.5 |
Conclusion: For the time being, if I have to work with an array to store and find, may be I'll continue to stick with typical C# code. As we can see, no matter how many records are there, LINQ to collection takes at least twice as much ticks as the regular code. The important thing for me is that if we had to find 1 millionth entry, LINQ took approximately 13 times more ticks than a regular loop!!!
I will try some other tests whenever I get opportunity. Stay tuned!
Disclaimer : I am no performance testing genius. I have tested it just for my own sake. If you feel that you would like to stress test LINQ yourself, use the code provided here and tweak it accordingly to test the performance yourself.