Q:

ObjC vs. MonoTouch float and array performance

EDIT : Added unsafe version of C# code. Thank you guys for this suggestion, the unsafe C# code runs faster, but only about 3%.

Short version: I wrote some benchmark code in C# and in Objective-C and tested it on the iPad 3. The MonoTouch/C# version needed between 50%-150% more time to execute than the same code in Objective-C. Here's my question: Can I write C# code which executes faster than the code I used for the benchmark (see below), or is this caused by some inherent MonoTouch/Obj-C difference?

Long version: I just wrote a small prototype for a planned multi-platform game. After porting the game core from Windows/.NET to the iPad 3/MonoTouch, I noticed how much slower the code ran on the iPad. Certain crucial parts of the game core ran about 10 times slower on the iPad CPU than on the Intel CPU (which seems to be normal because the iPad runs with an ARM processor).
However, since this is a major problem for our game, I ran a small benchmark test on the iPad 3, once with MonoTouch, and then the same thing with plain Objective-C. The benchmark does a lot of simple float additions and float array lookups. Since MonoTouch is GC'ed, I expected to see a small difference in favor of Obj-C, but to my astonishment, the MonoTouch code needed much more time to run than the Obj-C code. To be precise:

The Obj-C code needed 47'647 ms to run in DEBUG mode, and 27'162 ms in RELEASE mode.
The MonoTouch code without the use of unsafe pointers needed 116'885 ms to run in DEBUG mode, and 40'002 ms in RELEASE mode.
The MonoTouch code with unsafe pointers needed 90'372 ms to run in DEBUG mode, and 38'764 ms in RELEASE mode.

Of course, the RELEASE mode is what I care about.
This difference seems a bit high to me, given the fact that MonoTouch compiles to the same native LLVM code as Obj-C.
Here is the Obj-C code I used:
int i, j;
long time = GetTimeMs64();
float * arr = (float *) malloc(10000 * sizeof(float)); //  10'000
for (j = 0; j < 100000; j++) {                         // 100'000
    arr[0] = 0;
    arr[1] = 1;
    for (i = 2; i < 10000; i++) {                      //  10'000
        arr[i] = arr[i - 2] + arr[i - 1];
        if (arr[i] > 2000000000) {             // prevent arithm. overflow
            arr[i - 1] = 0;
            arr[i] = 1;
        }
    }
}
long time2 = GetTimeMs64() - time;

GetTimeMs64() uses <sys/time.h>'s gettimeofday.
Here my C#/MonoTouch code, in the unsafe version:
var array = new float[10000];                          //  10'000
var watch = System.Diagnostics.Stopwatch.StartNew();
fixed (float* arr = array)
{
    for (int j = 0; j < 100000; j++)                   // 100'000
    {
        *(arr + 0) = 0;
        *(arr + 1) = 1;
        for (int i = 2; i < 10000; i++)                //  10'000
        {
            *(arr + i) = *(arr + i - 2) + *(arr + i - 1);
            if (*(arr + i) > 2000000000)               // prevent arithm. overflow
            {
                *(arr + i - 1) = 0;
                *(arr + i) = 1;
            }
        }
    }
}

watch.Stop();

EDIT 2: This is the answer we got from Xamarin:

There are two issues with this particular example that impair mono
  performance.
First, if you're using the default MonoTouch compiler, and not LLVM,
  you can expect lower performance as it's tunned for compilation speed
  and not execution speed. LLVM will give you better results.
Second, mono complies with the ECMA spec regarding floating point and
  does all computations with double precision. This usually have a
  measurable performance cost specially if compared to C code using
  floats.
We've been looking into ways to relax the double precision performance
  without compromising correctness or, at least, have an opt in
  mechanism.

A:

Like Marc suggested you should use unsafe code, MonoTouch supports this .NET feature.
That will remove the .NET array-bounds checks which are a nice, safer, feature of .NET but has performance penalties (since each array access must be checked). 
That will make your code looks more (both in source and natively) looks like the Objective-C code and performance should be closer. Still I advice you to use unsafe code only when performance really matters (and after measuring that the gain are worth it).

