Saturday, October 16, 2010

De-Linking LINQ

For learning LINQ the best option is to check MSDN for references and then experiment.For days I was mystified with LINQ. How does it perform? One of the interesting features, that I found out is deferred execution of LINQ. So I decided to put forward some experimental program to test out the performance of LINQ and foreach construct. I have considered a load of 50000 records in the list of Objects. So here goes the code that I used:

Test Program

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace Wonder
{

/*Main Console Program For Testing Performance of LINQ and ForEach*/

class Program
{
const int LIMIT = 50000;
static SourceRecordList recordSet = new SourceRecordList();
static SourceRecord record;

static void Main(string[] args)
{
LoadData();
TestLinq();
TestForEach();
}

static void LoadData()
{
/*Load Data*/

for (int index = 0; index <= LIMIT; index++)
{
record = new SourceRecord(index, "Data" + index.ToString(), LIMIT - index, true);
recordSet.Add(record);
}
}

static void TestForEach()
{
for (int index = 0; index <= LIMIT; index++)
{
Stopwatch timeTracker = new Stopwatch();

if ((index == LIMIT || index == LIMIT / 2 || index == 1))
{
/*Testing Performance of For Each Loop in Finding Records, without breaking from Loop*/

bool found = false;
timeTracker.Reset();
timeTracker.Start();
foreach (SourceRecord recordItem in recordSet) { if (recordItem.ID == index) { found = true; } }
timeTracker.Stop();
Console.WriteLine("Using ForEach (Without breaking From Loop) Searched " + index.ToString() +
" in " + timeTracker.ElapsedTicks.ToString() + " ticks");

/*Testing Performance of For Each Loop in Finding Records, breaking from Loop, once found*/

found = false;
timeTracker.Reset();
timeTracker.Start();
foreach (SourceRecord recordItem in recordSet) { if (recordItem.ID == index) { found = true; break; } }
timeTracker.Stop();
Console.WriteLine("Using ForEach (Exiting loop, once found) Searched " + index.ToString() +
" in " + timeTracker.ElapsedTicks.ToString() + " ticks");
}
}
Console.ReadLine();
}
static void TestLinq()
{
for (int index = 0; index <= LIMIT; index++)
{
Stopwatch timeTracker = new Stopwatch();
if ((index == LIMIT || index == LIMIT / 2 || index == 1))
{
/*Testing LINQ performance for building Expression Tree*/

timeTracker.Reset();
timeTracker.Start();
var searchResult = from recordItem in recordSet where recordItem.ID == index select recordItem;
timeTracker.Stop();
Console.WriteLine("Expression Tree built in:" + timeTracker.ElapsedTicks.ToString() + " ticks");

/*Testing LINQ performance for executing same LINQ first time*/

timeTracker.Reset();
timeTracker.Start();
Console.WriteLine("First Execution of LINQ to Find " + searchResult.First().ID.ToString() +
" in " + timeTracker.ElapsedTicks.ToString() + " ticks");
timeTracker.Stop();

/*Testing LINQ performance for executing same LINQ second time*/

timeTracker.Reset();
timeTracker.Start();
Console.WriteLine("Second Execution of LINQ to Find " + searchResult.First().ID.ToString() +
" in " + timeTracker.ElapsedTicks.ToString() + " ticks");
timeTracker.Stop();
Console.ReadLine();
}
}
}
}
}

Entity:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Wonder
{

/*Data Structure Used For Demonstration*/

public class SourceRecord
{
public int ID { get; set; }
public string Name { get; set; }
public int DisplayOrder { get; set; }
public bool IsValid { get; set; }

public SourceRecord(int id, string name, int displayOrder, bool isValid)
{
ID = id;
Name = name;
DisplayOrder = displayOrder;
IsValid = isValid;
}
}

public class SourceRecordList : List
{
}
}

The execution result seemed interesting as well. You should try out this sample or experiment out yourself, but it is really worth conducting the performance test, which reveals many stories and faces of the mystified LINQ in action.

There are multiple opinions and people have concluded in multiple ways, for this loved and hated deferred execution feature of LINQ. I would rather leave space for thought for the reader and would just say that "Think before you use LINQ"!!


See http://msdn.microsoft.com/en-us/netframework/aa904594.aspx for learning references on LINQ.


No comments:

Post a Comment