3

我正在玩一个本机库,我为此编写了 monotouch(我们现在应该命名那个 Xamarin.iOS 吗?)绑定。

覆盖 C# 中一些常用的方法会导致性能严重下降,即使函数的核心什么也不做或返回 base.X()。Instruments 确认了问题以及在托管<->本机交互中花费的时间。

有没有办法从一侧或另一侧(本地或托管)加快速度?或者这是在 MT 中 P/Invoking 时要缴纳的税款?

我达到的玻璃天花板约为 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. 根据Mono touch 中的子类绑定类型,它仅适用于设备。我在 iPad mini 上获得 20 到 22.5 fps。

4

2 回答 2

4

我们现在应该命名那个 Xamarin.iOS 吗?

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

或者这是在 MT 中 P/Invoking 时要缴纳的税款?

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

此外,您可能会多次进行转换,例如new Managed ();调用 nativeinit*调用(native)setFoo:返回到(托管)Foosetter(并返回......调用者)。

因此,即使每个部分都很快,如果您不执行任何操作(或只是调用base),它仍然会值得注意,因为没有太多的用户时间可以摊销。

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

是的。首先确保你测量的是真实的东西。例如

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

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

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

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

事实证明,链接器在绑定方面非常聪明,并且可以删除您的情况不需要的代码。例如

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

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

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 不存在,那么可以添加它 - 但这应该是最少的选择(可能在其他地方进行优化会为您带来更大的回报)。

于 2013-02-20T18:49:36.287 回答
0

通过您奇怪的崩溃错误问题,我注意到 cocos2d 代码一直跳回单触领域,因为绑定导出了每个具有目标 c 名称的方法的所有单声道版本。我想知道你是否可以在不暴露的情况下重做绑定并获得巨大的速度提升?

除非您覆盖特定方法,否则您似乎不需要(或实际上不想要)那些公开的 - 在这种情况下,您可以为覆盖的方法添加 Objective-c 导出......我没有这样做,并且不知道是不是自找麻烦。如果 objc 端从不回调,除非您在那里有自定义代码,否则事情似乎会更好。

很想听听 poupou 或其他 xamarin 人对此发表评论!

于 2013-02-20T19:49:44.350 回答