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

Monday, 1 March 2010

Copying a Folder to and from Windows with rsync

Suppose you’ve got a NAS, or *nix box which has an rsync daemon running on it.

You’ve also got the convenient cwrsync bundle installed on your Windows box.

Now you want to be able to copy all the files in a folder on the windows box, say:

C:\foo\my spaced path\things

to and from the rsync module on your server.

To copy from the server to Windows

"c:\Program Files (x86)\cwRsync\bin\rsync.exe" -v -r -c rsync://@server/module /cygdrive/c/foo/"my spaced path"/things

This assumes the default installation path for cwrsync, you should drop the “ (x86)” if you’re not running on a 64-bit version of Windows.

The parameters include

  • -v for verbose
  • -c to always test file checksums rather than timestamps. If you’re happy that the timestamps are reliable, replace it with a –t to use (and copy) the timestamps.
  • -r for recursive.

The path on the Windows box has been munged to cygwin’s standards to look like a *nix path. 

  • The slashes all go forwards
  • The /cygdrive/c is the equivalent of “C:”
  • Any directory names that have spaces need a quote around their name, not around the path as a whole.

The path to the server specifies the rsync protocol, and the server name and module (like a share name in Windows/Samba/CIFS). I’ve not shown any user or password specification.

To copy from Windows to the server

"c:\Program Files (x86)\cwRsync\bin\rsync.exe" -v -c -r --no-perms --chmod=ugo=rwX /cygdrive/c/foo/"my spaced path"/things/ rsync://@server/module

Note the trailing slash after the Windows folder name. Without that, you’ll get a subfolder called “things” created under the module on your server.

I added the no-perms and chmod parameters because otherwise the ACLs that rsync placed on the copied files gave no rights to anyone.