In previous versions of .net (x64 .net 2), as a result of experimenting with the profiler and forming beliefs (whether true or false :-) that:
- property accesses are expensive
- bounds checks are not eliminated for static member arrays (this one was correct, as Greg Young proves).
- parallel array accesses do not have the bounds checks optimized away
So, for consistency, I always wrote loops like this, with a local reference to the array and a variable in the loop scope holding the end limit.
int z = 0; var localArray1 = memberArray1; var localArray2 = memberArray2; for (int x = 0, length = localArray1.Length; x < length; x++) { z += localArray1[x] + localArray2[x]; }
Recently, I re-examined this practice with Visual Studio 2010 RC and the disassembly window. I wanted to find out what the best pattern would be consistency and allowing the JIT to hoist the bounds checks, eliminating them from the per-iteration part of the loop.
.net 2
x86 and x64 JITs were both unable to remove the bounds checks.
Rewriting the for loop to read
for (int x = 0; x < localArray1.Length; x++)
Allowed the x86 JIT to eliminate one of the bounds checks. The x64 JIT still had both.
.net 4
The x86 JIT still had both bounds checks. The x64 JIT eliminated one.
Rewriting the for loop to read
for (int x = 0; x < localArray1.Length; x++)
The x86 now had only one bounds check. The x64 eliminated both.
Conclusions
- Don’t use a local variable to hold your array stopping condition.
- Experiment with both ‘Any CPU’ and ‘x86’ if possible.
- Check out the disassembly (step-by-step explanation by Vance Morrison).