For vs. Foreach Follow up (part 1)

I’m writing this piece in a response to Jackson Dunstan’s piece about the speed of For vs. Foreach. He got some really peculiar results for using foreach with arrays and I’ve decided that I need to go deeper. Look what I’ve found out.


Before I proceed let me do a small disclaimer:
As part of my work at Caped Koala Studios I’m doing a small marketing push just to reach anyone who might be interested in playing educational games for children. See poraora.com if you are looking for games for your kids or are just interested in what happens in the edutainment space.

 
Following the discussion in the comments of Jackson’s article about the test’s fairness I’ve decided to tweak it a little bit to make sure we do some work in the loops and the the compiler is not skipping anything.

In my test I’ve changed the following things:

  1. Changed the object to a simple Counter class with a single int field for both array and list
  2. Added a single int incrementation to every loop in the test to make sure we do something “nontrivial” there

Here is the code I’ve used:

Similarly to how Jackson’s tests are structured – If you want to try out the test yourself, simply paste the above code into a ForVsForeach.cs file in your Unity project’s Assets directory and attach it to the main camera game object in a new, empty project. Then build in non-development mode for 64-bit processors and run it windowed at 640×480 with fastest graphics. I ran it that way on this machine:

  • 3.5 GHz Intel Core i7-4770,
  • Windows 8.1,
  • Unity 5.1.2f1, Windows Standalone, x86_64, non-development,
  • 640×480, Fastest, Windowed

 

And here are the results I got are very different. In my case foreach instead of being twice as fast for arrays turned out to be at best half as fast for both arrays and generic lists (time in ms):

Size Array For Array Foreach List For List Foreach
10 1 2 3 15
100 10 22 36 85
1000 96 221 358 801

ForVsForeachSize10_x86_64

ForVsForeachSize100_x86_64

ForVsForeachSize1000_x86_64

 
 

Interestingly the results I’ve got for the x86 (32b) build are very different. Here foreach and for give the same results for arrays but not for lists (time in ms):

Size Array For Array Foreach List For List Foreach
10 1 1 5 16
100 11 12 40 94
1000 112 115 389 877

ForVsForeachSize10

ForVsForeachSize100

ForVsForeachSize1000

After a very brief spark of enthusiasm for using foreach with arrays I’m going back to defaulting to for as the loop of choice. The extra benefit being not having to worry about allocations when using it with generic lists.

I’ve also put a method into the code above for you to test out how complicated the code inside the loop needs to be for this optimization to become irrelevant. This is a reminder of premature optimization concept.

You should be looking for iteration optimizations like using unsafe code loops only in case when your doing really simple things inside the loops. Otherwise you’ll be better off by (preferably) changing the algorithm to a better option or by fiddling with whatever you are doing inside the loop.

Thanks for reading. (pun intended)

P.S. If you are curios what I’m working on currently check out the poraora.com :)

P.S. This turned out to be a two-part series and you can read the second part here :).

1 Comment

  1. Pingback: Loop Performance: For vs. Foreach vs. While « JacksonDunstan.com

Leave a Comment

Your email address will not be published. Required fields are marked *