Wednesday, 24 March 2010

.net 4 C# Parallel Array Bounds Checking

In previous versions of .net (x64 .net 2), as a result of experimenting with the profiler and forming beliefs (whether true or false :-) that:



  1. property accesses are expensive


  2. bounds checks are not eliminated for static member arrays (this one was correct, as Greg Young proves).


  3. 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).