I wrote the following to test the performance of using foreach
vs LINQ
:
private class Widget
{
public string Name { get; set; }
}
static void Main(string[] args)
{
List<Widget> widgets = new List<Widget>();
int found = 0;
for (int i = 0; i <= 500000 - 1; i++)
widgets.Add(new Widget() { Name = Guid.NewGuid().ToString() });
DateTime starttime = DateTime.Now;
foreach (Widget w in widgets)
{
if (w.Name.StartsWith("4"))
found += 1;
}
Console.WriteLine(found + " - " + DateTime.Now.Subtract(starttime).Milliseconds + " ms");
starttime = DateTime.Now;
found = widgets.Where(a => a.Name.StartsWith("4")).Count();
Console.WriteLine(found + " - " + DateTime.Now.Subtract(starttime).Milliseconds + " ms");
Console.ReadLine();
}
I get something like following output:
31160 - 116ms 31160 - 95 ms
In every run, LINQ outperforms foreach by around 20%. It was my understanding that the LINQ extension methods used standard c# under the covers.
So why is LINQ faster in this case?
EDIT:
So I changed my code to use stopwatch instead of datetime and still get the same results. If I run the LINQ query first then my results show LINQ to be about 20% slower then foreach. This has to be some sort of JIT warmnup issue. My question is how do I compensate for JIT warmup in my test case?
If a new method is thought up that's incredibly fast, the people at Microsoft can implement it without even telling you and your code would be a lot faster. More importantly though, LINQ is just much easier to read. That should be enough reason.
LINQ is absolutely 100% slower You are going to essentially "stall-out" if you are performing any complex queries, joins etc...
LINQ syntax is typically less efficient than a foreach loop. It's good to be aware of any performance tradeoff that might occur when you use LINQ to improve the readability of your code.
It's because you do not have a warmup. If you reverse your cases you will get excatly the opposit result:
31272 - 110ms
31272 - 80 ms
Start adding a warmup and use a stopwatch for better timing.
Running the test with warmup:
//WARM UP:
widgets.Where(a => a.Name.StartsWith("4")).Count();
foreach (Widget w in widgets)
{
if (w.Name.StartsWith("4"))
found += 1;
}
//RUN Test
Stopwatch stopwatch1 = new Stopwatch();
stopwatch1.Start();
found = widgets.Where(a => a.Name.StartsWith("4")).Count();
stopwatch1.Stop();
Console.WriteLine(found + " - " + stopwatch1.Elapsed);
found = 0;
Stopwatch stopwatch2 = new Stopwatch();
stopwatch2.Start();
foreach (Widget w in widgets)
{
if (w.Name.StartsWith("4"))
found += 1;
}
stopwatch2.Stop();
Console.WriteLine(found + " - " + stopwatch2.Elapsed);
result:
31039 - 00:00:00.0783508
31039 - 00:00:00.0766299
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With