Benchmark of foreach .vs. for loop

The foreach loop provides a nice way to iterate through a generic container.  But, is there a price to pay for it performance wise .vs. using a for loop? It turns out that there is a performance hit when using a foreach loop.

The following benchmark code was used to determine how well a foreach loop compares against a for loop. The code was run 5 times in release mode, and the average taken:

Time Elapsed for the for loop = 5 ms
Time Elapsed for the for next loop = 12 ms – press a key to continue.

Time Elapsed for the for loop = 6 ms
Time Elapsed for the for next loop = 12 ms – press a key to continue.

Time Elapsed for the for loop = 6 ms
Time Elapsed for the for next loop = 12 ms – press a key to continue.

Time Elapsed for the for loop = 5 ms
Time Elapsed for the for next loop = 12 ms – press a key to continue.

Time Elapsed for the for loop = 6 ms
Time Elapsed for the for next loop = 12 ms – press a key to continue.

Total for the for loop = 33ms. Avg = 28 / 5 = 5.6ms for 2M iterations.
Total for the foreach loop = 60ms. Avg = 60 / 5 = 12ms for 2M iterations.

Average ratio = 12 / 5.6 = 2.14.

RESULT: The for loop is a little more than twice as fast as the foreach loop.

The code is given below:

public abstract class Color
{
    public abstract int DoMethod();
}

class RedColor : Color
{
    private int Value;
    public int TestValue
    {
        get { return Value; }
        set { Value = value; }
    }

    public RedColor()
    {
        Value = 0;
    }

    public RedColor(int value)
    {
        Value = value;
    }

    public override int DoMethod()
    {
        return Value;
    }
 }

public static void BenchmarkFor()
{
    // This method benchmarks the relative performance of using a for next loop .vs. a foreach loop.
    //
    const int Iters = 2000000;
    int Loop;
    // NOTE - RedColor is a very simple class. It can really be anything. 
    List<RedColor> GenList = new List<RedColor>(Iters);
    RedColor RC;
    GenericFactory<string> GenFact = new GenericFactory<string>();
    // Fill the list of objects.
    for (Loop = 0; Loop < Iters; Loop++)
    {
       RC = new RedColor(Loop);
       GenList.Add(RC);
    }
    // Clean up before starting.
    GC.Collect();
    // Begin the for next loop test.
    var Watch = new Stopwatch();
    Watch.Start();
    for (int i = 0; i < Iters; i++)
    {
       RC = GenList[i];
       RC.TestValue = RC.TestValue + 1;
    }
    Watch.Stop();
    Console.WriteLine("Time Elapsed for the for loop = {0} ms", Watch.ElapsedMilliseconds);
    // Begin the foreach loop test.
    Watch = new Stopwatch();
    Watch.Start();
    foreach(RedColor RC1 in GenList)
    {
        RC1.TestValue = RC1.TestValue + 1;
    }
    Watch.Stop();
    Console.WriteLine("Time Elapsed for the for next loop = {0} ms - press a key to continue.", Watch.ElapsedMilliseconds);
    Console.ReadKey();
}
Advertisements

About Bob Bryan

Software developer for over 20 years. Interested in efficient software methodology, user requirements, design, implementation, and testing. Experienced with C#, WPF, C++ , VB, Sql Server, stored procedures, and office tools. MCSD.
This entry was posted in C#, efficient software development and tagged , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s