Why Enumerable.Range is faster than a direct yield loop?
- by Morgan Cheng
Below code is checking performance of three different ways to do same solution.
public static void Main(string[] args)
{
// for loop
{
Stopwatch sw = Stopwatch.StartNew();
int accumulator = 0;
for (int i = 1; i <= 100000000; ++i)
{
accumulator += i;
}
sw.Stop();
Console.WriteLine("time = {0}; result = {1}", sw.ElapsedMilliseconds, accumulator);
}
//Enumerable.Range
{
Stopwatch sw = Stopwatch.StartNew();
var ret = Enumerable.Range(1, 100000000).Aggregate(0, (accumulator, n) => accumulator + n);
sw.Stop();
Console.WriteLine("time = {0}; result = {1}", sw.ElapsedMilliseconds, ret);
}
//self-made IEnumerable<int>
{
Stopwatch sw = Stopwatch.StartNew();
var ret = GetIntRange(1, 100000000).Aggregate(0, (accumulator, n) => accumulator + n);
sw.Stop();
Console.WriteLine("time = {0}; result = {1}", sw.ElapsedMilliseconds, ret);
}
}
private static IEnumerable<int> GetIntRange(int start, int count)
{
int end = start + count;
for (int i = start; i < end; ++i)
{
yield return i;
}
}
}
The result is like this:
time = 306; result = 987459712
time = 1301; result = 987459712
time = 2860; result = 987459712
It is not surprising that "for loop" is faster than the other two solutions, because Enumerable.Aggregate takes more method invocations. However, it really surprises that "Enumerable.Range" is faster than the "self-made IEnumerable". I thought that Enumerable.Range will take more overhead than the simple GetIntRange method.
What is the possible reason for this?