Friday, May 27, 2011

for loop vs foreach vs fordelegate vs LINQ vs Lambda loops

By seeing below report foreach is almost equal to lambda expression

Report - each Method 10 Iteration
Method Name : For :52
Method Name : ForEach :29
Method Name : ForEachDelegate :25
Method Name : Linq :37
Method Name : Lambda :33


Important - Run the code in Release Mode


static void Main(string[] args)
{
Test t = new Test();
t.AllTests();
}

class Avg
{
public int Time { get; set; }
public string MethodName { get; set; }
}

class Test
{
delegate void TestMethod();
List m_Source = new List();
List Average = new List();
System.Diagnostics.Stopwatch m_Watch
= new System.Diagnostics.Stopwatch();

public void AllTests()
{
for (int i = 0; i < 1000000; i++)
m_Source.Add(i);
TestMethod _TestFor = new TestMethod(TestFor);
TestMethod _TestForEach = new TestMethod(TestForEach);
TestMethod _TestForEachDelegate = new TestMethod(TestForEachDelegate);
TestMethod _TestLinq = new TestMethod(TestLinq);
TestMethod _TestLambda = new TestMethod(TestLambda);
//TestMethod _TestParallel = new TestMethod(TestParallel);

// how many time to repeat each test?

for (int i = 1; i < 10; i++)
{
TestThis(_TestFor);
TestThis(_TestForEach);
TestThis(_TestForEachDelegate);
TestThis(_TestLinq);
TestThis(_TestLambda);
//TestThis(_TestParallel);
Console.WriteLine(string.Empty);
}
var a1 = (from a in Average
group a by a.MethodName into g
select new { MethodName = g.Key, AvgTime = g.Sum(a2 => a2.Time) / g.Count() }).ToList();

foreach (var g in a1)
{
Console.WriteLine("Method Name : {0} :{1}", g.MethodName, g.AvgTime);
}

Console.Read();
}

void TestThis(TestMethod test)
{
m_Watch.Reset();
m_Watch.Start();
test.Invoke();
var _Time = (int)m_Watch.Elapsed.TotalMilliseconds;
var _Method = test.Method.Name.Replace("Test", string.Empty);
var _Result = string.Format("{1}\t{0}", _Method, _Time);
Average.Add(new Avg() { MethodName = _Method, Time = _Time });
Console.WriteLine(_Result);
}

void TestFor()
{
var _Target = new List();
for (int i = 0; i < m_Source.Count(); i++)
_Target.Add(m_Source[i] + 1);
_Target.ToArray().Count();
//Debug.Assert(m_Source.Count() == _Target.ToArray().Count());
}

void TestForEach()
{
var _Target = new List();
foreach (int i in m_Source)
_Target.Add(i + 1);

_Target.ToArray().Count();
//Debug.Assert(m_Source.Count() == _Target.ToArray().Count());
}

void TestForEachDelegate()
{
var _Target = new List();
m_Source.ForEach((int i) =>
{
_Target.Add(i + 1);
});
_Target.ToArray().Count();
//Debug.Assert(m_Source.Count() == _Target.ToArray().Count());
}

void TestLinq()
{
var _Target = from i in m_Source
select i + 1;
_Target.ToArray().Count();
//Debug.Assert(m_Source.Count() == _Target.ToArray().Count());
}

void TestLambda()
{
var _Target = m_Source.Select(i => i + 1);
_Target.ToArray().Count();
//Debug.Assert(m_Source.Count() == _Target.ToArray().Count());
}

void TestParallel()
{
// TODO
}
}

1 comment:

  1. You have use the IEnuemrable.Count() method in the for loop's condition test. This enumerates the entire list on each iteration. Change it to the Count property, and for outperforms all other tests on my machine.

    ReplyDelete