降低本地< - >的成本在monotouch中管理交互

时间:2013-02-20 16:48:09

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

我正在玩一个我编写单音素的本机库(我们现在应该将Xamarin.iOS命名为?)绑定。

覆盖C#中一些常用的方法会显示严重的性能降级,即使该函数的核心不执行任何操作或返回base.X()。 Instruments会确认问题以及在托管的< - >原生互动中花费的时间。

有没有办法从一方或另一方(本机或托管)加快速度?或者这是在P / Invoking MT时支付的税款吗?

我打的玻璃天花板大约是50000次/秒。

[更新2013/02/22] 为了给出一些背景或例子,这就是我正在做的事情。我正在玩cocos2d运动学(没有花栗鼠)。为了管理我自己的精灵位置,我必须覆盖

CGAffineTransform NodeToParentTransform { get; }

bool Dirty { get; }

前者返回矩阵,并戳戳本机端以获取ScaleX,ScaleY,RotationX等参数。 RotationY和AnchorPointInPoints,后者无条件地返回true

我目前在降低成本方面的尝试部分成功,因为通过将原生代码更改为具有单个点来覆盖而不会攻击任何属性,我获得了25%到50%的加速。

-(BOOL) dirty:(CGAffineTransform*)nodeToParentTransform rotationX:(float)rotX rotationY:(float)rotY scaleX:(float)scaleX scaleY:(float)scaleY anchorPointInPoints:(CGPoint)anchorPointInPoints;

我现在为我的3500精灵获得了几乎可以接受的25-30fps,但是我仍然希望更进一步。而且也不必修补原生资源。

[更新2013/02/22 2] 以下是您可以用来测试https://github.com/StephaneDelcroix/mt-speed的示例。它包含一个简化的一阶动态引擎,3501个实体和精灵。

这里有趣的课程是KinematicSprite。代码适用于cocos2d的修改版本(包含在Cocos2D.dll中)。您可以通过注释掉新的Dirty函数并取消注释NodeToParentTransform和旧Dirty,使其适用于库存cocos2d和cocos2d绑定。根据{{​​3}},它仅适用于设备。我在iPad mini上得到20到22.5 fps。

2 个答案:

答案 0 :(得分:4)

  

我们现在应该将Xamarin.iOS命名为吗?

是的,现在是Xamarin.iOS: - )

  

或者这是在P / Invoking MT时付的税吗?

从托管代码和非托管代码转换时,有很多事情要做。蹦床处理这个问题:编组参数和返回值,处理托管异常,处理本机异常......

您也可能多次进行过渡,例如new Managed ();调用本机init*调用(本机)setFoo:,后者返回(托管)Foo setter(并返回...给调用者)。

因此,即使每个部分都很快,如果你做了一个no-op(或只是调用base),因为没有多少用户时间来分摊,所以即使每个部分都很快。 / p>

  

有没有办法从一方或另一方(本机或托管)加快速度?

是。首先确保你测量真正的事物。例如。

  • 上述任务与模拟器和设备不同,例如: JIT与AOT,x86和ARM的不同ABI;

  • 调试和发布构建配置也将使用不同的代码;

因此,您可能希望在iOS(ARM)设备上测量版本构建。

您应该做的下一件事是确保启用链接所有程序集(如果您有非SDK绑定,例如Cocos2d)。这不会改变蹦床,但是当你打电话给base时,你正在调用绑定代码。

事实证明,链接器非常智能关于绑定,并且可以删除在您的情况下不需要的代码。 E.g。

编辑:启用链接器的另一个原因是它删除了绑定中的额外(未使用)方法 - 使本机代码不太可能需要回调到托管世界(和较少的过渡意味着更快的时间)

其他方式更具侵入性,可能需要更改代码以最大限度地减少托管代码和本机代码之间的聊天。例如。有时你可以打电话

var x = new X (1, 2, 3, 4);

var x = new X ();
x.a = 1;
x.b = 2;
x.c = 3;
x.d = 4;

你可以猜测第一种情况需要更少的过渡(并且更快)。如果这样的API不存在,那么可以被添加 - 但这应该是一个最不可取的选择(可能还有其他优化会让你获得更大回报的地方)。

答案 1 :(得分:0)

通过你的奇怪的崩溃bug问题,我注意到cocos2d代码一直跳回到monotouch的土地,因为绑定导出每个方法的所有单声道版本与objective-c名称。我想知道你是否可以在没有暴露的情况下重做绑定并获得巨大的速度?

除非你覆盖特定的方法,否则你似乎不需要(或者真的想要)那些暴露 - 在这种情况下你可以为你的重写方法添加objective-c导出...我还没有完成这个,我不知道它是否在寻找麻烦。如果objc方面从未回调过,除非你在那里有自定义代码,否则看起来事情会更好。

很想听到poupou或其他xamarin家伙发表评论的评论!