For vs foreach: the performance difference will shock you

I recently started looking at performance optimization applicable in Unity. Doing Google searches showed out-of-date tests (much like this could be if you are reading in the far future).

I’m specifically trying to determine which type of loop (For Vs. ForEach) is the most efficient to use as 1) referencing GameObjects and 2) modifying a value.

For these tests I’m using Unity 2020.3.19f1 LTS on Windows 10 with an i9-10850 CPU with 16GB RAM. For updating values, the GameObject position was changed. I ran the test seven times and used the average to come to a conclusion. This is more as a reference rather than the “be all and end all” of which case suits your best. Basically, do your own tests to see how each case would suit your own needs.

Without further ado, here is are my test results iterating an array of 100,000 GameObjects:

Results

Editor

IL2CPP EditorRead ValueSet Value
ForForEachForForEach
0.0033917430.0036640170.067594050.04567719
0.0034174920.0035285950.063674450.04667139
0.003467560.0035200120.066828730.05114985
0.0033812520.003345490.062442780.04349947
0.0034904480.0034618380.060833450.04655266
0.0034084320.0035433770.063357350.04396629
0.0035672190.0035228730.062111380.04444933
Editor For v ForEach Times in Seconds
Average0.0034463065710.0035123145710.063834598570.04599516857
Difference0.000066008-0.000066008-0.017839430.01783943
Editor For v ForEach Time differences in Seconds

Player Build

IL2CPP PlayerRead ValueSet Value
ForForEachForForEach
0.00063562390.00054788590.043213840.0290904
0.00063371660.00054359440.041841030.02432728
0.00062608720.00066947940.03976250.02416563
0.00062561040.00052881240.037984850.02457619
0.00064945220.00054883960.043627740.02631426
0.00062751770.00053358080.038517480.02418947
0.00063562390.00055551530.038239240.02412081
Player For v ForEach Times in Seconds
Average0.00063337598570.00056110111430.040455240.02525486286
Difference-0.000072274871430.00007227487143-0.015200377140.01520037714
Player For v ForEach Time differences in Seconds

Conclusions

First off, Unity Editor has a lot of overhead and is going to be always much slower than a build. Testing in Unity Editor will help determine if there are easy performance gains. When you want to get more realistic values you need the Player build used by players.

Comparing Timings between the Editor and Player build when reading elements in an array

Comparing the Editor to the Player build, and reading values from an array timings move from the 100ths into the 1000ths of a second. Setting values is much slower than reading values measured in 10ths. Modifying elements in a list has a performance cost, so don’t update elements needlessly (much like you shouldn’t in any kind of game loop, i.e. Unity’s Update()).

Reading elements in an array

Does it significantly matter if you are using a For or ForEach loop when reading elements in an array? We are talking 10,000ths of a second. Not a significant difference between the two. If you want the fastest iteration possible then ForEach wins when reading elements in an array.

Comparing Timings between the Editor and Player build when writing elements in an array

Modifying a GameObject value has its performance cost (probably more due to using the position Vector3 array which is a struct) and the difference is 2/100ths of a second, and significantly more costly than just reading values.

Writing elements in an array

ForEach is 15/100th faster than For. This difference is not going enough to worry about on its own but ForEach is faster and the best choice for getting as much performance as you can.

Other considerations

A last-minute thought, quite literally, any garbage collection from using a For or ForEach. Several years back ForEach generated garbage, then an update improved its performance. This experiment has not taken this into consideration and could make a considerable difference in how much Garbage is generated and thus make Garbage collection run more frequently, slowing performance and increasing frame hitches.

Testing on a variety of target machines could impact performance differently.

Using Mono scripting backend could impact performance differently.

TL;DR: ForEach was faster than For in this experiment. That alone should not influence any decision-making process.

UPDATE

Garbage collection was skewing the results. The first time you access the .transform for a GameObject Unity generates garbage.

I got around this by just doing an initial iteration before testing the times. From some initial testing ‘For’ won 4 out of 7 times in the 1/100th’s of seconds.

Based on this there is not much potential for performance gains. It’s best to choose for or foreach based on the needs of the project.

This garbage generation on first time accessing the transform may be worth noting for anyone who pools gameobjects.