C# foreach VS for loop

When I started using C#, mainly because of XNA one of the things I got used to write is foreach loops instead of for, seemed easier and it’s a much cleaner code. Doing almost the same thing as a for loop I never really bother to see the differences, almost everyone in their XNA examples used it instead.

Today I decided to see the differences between them:

FOR

int[] values = new int[1];
int total = 0;
for(int i = 0; i < values.Length; i++)
{
    total += values[i];
}

FOREACH

int[] values = new int[1];
int total = 0;
foreach(int i in values )
{
    total += i;
}

In variable declaration, foreach has five variable declarations (three Int32 integers and two arrays of Int32) while for has only three (two Int32 integers and one Int32 array). When it goes to loop through, foreach copies the current array to a new one for the operation. While for doesn’t care of that part.

After the compiler interpretation to Assembly we get this:

FOR

cmp     dword ptr [eax+4],0           i
jle     0000000F
mov     ecx,dword ptr [eax+edx*4+8]
inc     edx
cmp     esi,dword ptr [eax+4]
jl      FFFFFFF8

FOREACH

cmp     esi,dword ptr [ebx+4]          i
jl      FFFFFFE3
cmp     esi,dword ptr [ebx+4]
jb      00000009
mov     eax,dword ptr [ebx+esi*4+8]
mov     dword ptr [ebp-0Ch],eax
mov     eax,dword ptr [ebp-0Ch]
add     dword ptr [ebp-8],eax
inc     esi
cmp     esi,dword ptr [ebx+4]
jl      FFFFFFE3

As you can see we end up with much more instructions.
Some simple tests gives these results:

Using Objects Using Integers
FOR FOREACH FOR FOREACH
ArrayList – 2147483 items 88.6 115.9 65.1 134
generic collection – 2147483 items 84.4 87.1 51.6 72.2
Array – 2147483 items 48.1 49.8 17.5 21.7

*Time is in milliseconds.

So what I’ve done after this was to replace some heavy foreach code on my engine by for loops. I guess small things can be neglected but it’s always nice to know where bottlenecks may happen.

5 Comments

  1. another “nice to know” article, Keep it up 🙂

  2. hi,

    First of all. Thanks very much for your useful post.

    I just came across your blog and wanted to drop you a note telling you how impressed I was with the information you have posted here.

    Please let me introduce you some info related to this post and I hope that it is useful for .Net community.

    There is a good C# resource site, Have alook

    http://www.csharptalk.com/2009/09/c-array.html
    http://www.csharptalk.com/2009/10/creating-arrays.html

    simi

  3. There’s another caveat in something simple.

    Take

    i++;

    and

    ++i;

    The first one generates a second temporary integer that has the value of i+1, then assigns that temp value to i after the end of statement (‘;”). While the second one just ups i with one.

    I think the .Net compiler/interpreter is smart enough most of the time to optimize a i++ to ++i (if possible). However since I know this I always use ++i in my for loops (and other code that just adds one).

  4. Swight

    I know this is an old post but it ranks fairly high on google so I am leaving this here for informational purposes.

    Almost all the foreach s in my game engine code have led to errors at some point. Mostly due to the fact the in a foreach loop the collection cannot be modified. For this reason I use reversed for loops(counting backwards) almost exclusively. Not only do they not flinch at being modified, they also handle things gracefully when the current element is removed. This is because the only elements that have changed indexes are the ones that have already been processed.

  5. Stein Gregory

    First of all thanks for pointing it out. Nice research.

    However the difference is not that important. ArrayList is totally deprecated today (replaced with fast generic collections). So the only somehow significant difference is in value types.

    Additionally, what you should look at is not an assembly language, but the MSIL. It’s far more important, since we have different architectures. You might want to check compiler output of Mono as well.

    I did also some testing and what I got is the following:

    Iterating through array of ints:

    [code]
    [Test]
    public unsafe void IsDenWpfRight()
    {
    const int ARRAY_SIZE = 1024*1024;
    var array = new byte[ARRAY_SIZE];// 1MB = 256 pages
    Random random = new Random();
    random.NextBytes(array);
    byte result = 0;
    Stopwatch stopwatch = new Stopwatch();
    stopwatch.Start();
    for (int i=0; i result = (byte)((result + i) % 251));
    stopwatch.Stop();
    Console.WriteLine(“Array.ForEach: ” + stopwatch.ElapsedTicks);
    }
    [/code]

    Results:
    for loop: 34426
    foreach loop: 27932
    Array.ForEach: 30604

    For objects and collections:

    [code]
    private class SomeClass
    {
    public int field;
    }
    [Test]
    public unsafe void IsDenWpfRight()
    {
    const int ARRAY_SIZE = 1024*1024;
    var list = new List();
    Random random = new Random();
    for (int i=0 ; i< ARRAY_SIZE; i++)
    {
    list.Add(new SomeClass() {field = random.Next()});
    }
    int result = 0;
    Stopwatch stopwatch = new Stopwatch();
    stopwatch.Start();
    for (int i=0; i<ARRAY_SIZE; i++)
    {
    result = ((result + list[i].field)%513); // avoid compiler optimization for %256
    }
    stopwatch.Stop();
    Console.WriteLine("for loop: " + stopwatch.ElapsedTicks);
    stopwatch.Reset();
    stopwatch.Start();
    foreach (var i in list)
    {
    result = ((result + i.field) % 513); // avoid compiler optimization for %256
    }
    stopwatch.Stop();
    Console.WriteLine("foreach loop: " + stopwatch.ElapsedTicks);
    }
    [/code]

    Results:
    for loop: 37629
    foreach loop: 35891

    From these tests I conclude that the performance of foreach is even better (maybe in some cases) or at least the same. So don't bother, write the style you like 🙂

    Happy coding.

Leave a Reply