ObjC vs. MonoTouch浮点和数组性能

时间:2012-09-14 16:09:57

标签: c# objective-c ios ipad xamarin.ios

编辑:添加了unsafe版本的C#代码。谢谢你们这个建议,unsafe C#代码运行得更快,但只有3%左右。


简短版本:我在C#和Objective-C中编写了一些基准代码,并在iPad 3上进行了测试.MonoTouch / C#版本需要比执行时间多50%-150% Objective-C中的相同代码。这是我的问题:我能编写的C#代码执行速度比我用于基准测试的代码(见下文)要快,还是由一些固有的MonoTouch / Obj-C差异引起的?


长版:我刚刚为计划好的多平台游戏编写了一个小型原型。在将游戏核心从Windows / .NET移植到iPad 3 / MonoTouch之后,我注意到代码在iPad上运行的速度有多慢。游戏核心的某些关键部分在iPad CPU上比在英特尔CPU上慢了约10倍(这似乎是正常的,因为iPad使用ARM处理器运行)。

然而,由于这是我们游戏的一个主要问题,我在iPad 3上进行了一次小型基准测试,一次使用 MonoTouch ,然后用简单的 Objective-C进行同样的操作即可。基准测试执行了许多简单的float添加和float数组查找。由于MonoTouch是GC,我希望看到Obj-C有一点不同,但令我惊讶的是,MonoTouch代码比Obj-C代码需要更多的时间来运行。确切地说:

  • Obj-C 代码需要47'647 ms才能在DEBUG模式下运行,27'162 ms需要在RELEASE模式下运行。
  • 不使用unsafe指针的 MonoTouch 代码需要116'885 ms在DEBUG模式下运行,40'002 ms在RELEASE模式下运行。
  • MonoTouch 代码 unsafe指针需要90'372 ms在DEBUG模式下运行,38'764 ms在RELEASE模式下运行。< / LI>

当然,RELEASE模式是我关心的。

鉴于MonoTouch编译为与Obj-C相同的本地LLVM代码,这种差异对我来说似乎有点高。

这是我使用的Obj-C代码:

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()使用<sys/time.h>的{​​{1}}。

这是我的C#/ MonoTouch代码,gettimeofday版本:

unsafe

编辑2:这是我们从Xamarin得到的答案:

  

此特定示例有两个问题会影响单声道   性能

     

首先,如果您使用的是默认的MonoTouch编译器,而不是LLVM,   你可以期待更低的性能,因为它已经调整了编译速度   而不是执行速度。 LLVM将为您提供更好的结果。

     

其次,单声道符合关于浮点和的ECMA规范   以双精度进行所有计算。这通常有一个   与使用C代码相比,特别是可衡量的性能成本   浮动。

     

我们一直在研究放松双精度性能的方法   没有妥协正确性,或者至少有选择权   机构。

1 个答案:

答案 0 :(得分:5)

与Marc建议你应该使用unsafe代码一样,MonoTouch支持这个.NET功能。

这将删除一个漂亮,更安全的.NET 功能的.NET数组边界检查,但会有性能损失(因为必须检查每个阵列访问 )。

这将使您的代码看起来更多(源代码和本机代码)看起来像Objective-C代码,性能应该更接近。我仍建议您仅在性能真正重要时使用unsafe代码(并且在衡量增益值得之后)。