The short question: Why is LINQ slower than looping via foreach for aggregation operations?
Description -
I am trying to optimize some old code and while LINQ queries are used extensively throughout the code, trivial operations like summing up numbers in an Enumerable
is done using loops.
So, I ran a little test to compare the performance of the two methods. Below is the code for computing sum of a 1000 numbers long enumerable using LINQ's .Sum()
method and using a foreach
loop and summing up each occurence manually.
List<Double> numbers = new List<Double>();
Double[] sums1 = new Double[1000];
Double[] sums2 = new Double[1000];
for (int i = 0; i < 1000; i++)
{
numbers.Add(i * i);
}
Int64 startTime1 = Stopwatch.GetTimestamp();
for (int i = 0; i < 1000; i++)
{
Double sum = 0;
sum = numbers.Sum();
sums1[i] = sum;
}
Int64 endTime1 = Stopwatch.GetTimestamp();
Int64 startTime2 = Stopwatch.GetTimestamp();
for (int i = 0; i < 1000; i++)
{
Double sum = 0;
foreach (Double number in numbers)
{
sum += number;
}
sums2[i] = sum;
}
Int64 endTime2 = Stopwatch.GetTimestamp();
Console.WriteLine("LINQ. Start = {0}, End = {1}: Diff = {2}", startTime1, endTime1, endTime1 - startTime1);
Console.WriteLine("ForEach. Start = {0}, End = {1}: Diff = {2}", startTime2, endTime2, endTime2 - startTime2);
I ran this test a couple (ten) times and the results were:
LINQ. Start = 117385428996, End = 117385462197: Diff = 33201
Foreach. Start = 117385462203, End = 117385476329: Diff = 14126
LINQ. Start = 117385478555, End = 117385499802: Diff = 21247
Foreach. Start = 117385499808, End = 117385520756: Diff = 20948
LINQ. Start = 117385521426, End = 117385546256: Diff = 24830
Foreach. Start = 117385546260, End = 117385567052: Diff = 20792
LINQ. Start = 117385572791, End = 117385602149: Diff = 29358
Foreach. Start = 117385602156, End = 117385622367: Diff = 20211
LINQ. Start = 117385623153, End = 117385652563: Diff = 29410
Foreach. Start = 117385652568, End = 117385673733: Diff = 21165
LINQ. Start = 117385674403, End = 117385705028: Diff = 30625
Foreach. Start = 117385705035, End = 117385725552: Diff = 20517
LINQ. Start = 117385726094, End = 117385753161: Diff = 27067
Foreach. Start = 117385753166, End = 117385771824: Diff = 18658
LINQ. Start = 117385772341, End = 117385793726: Diff = 21385
Foreach. Start = 117385793733, End = 117385811332: Diff = 17599
LINQ. Start = 117385811768, End = 117385837204: Diff = 25436
Foreach. Start = 117385837209, End = 117385852670: Diff = 15461
LINQ. Start = 117385853003, End = 117385874410: Diff = 21407
Foreach. Start = 117385874416, End = 117385891874: Diff = 17458
Note that the foreach
loop always performed better. What could be the reason for this?
Edit: An answer to this question has lot of good information about why the performance could be bad as compared to regular inline manipulations. But I am unable to see how exactly it could relate here.