因此,我实质上是在尝试实现AIR Native Extension,该接口(interface)通过Actionscript在C语言中进行物理模拟。

为了方便起见,我已经进行了很多迭代,下面将列出这些迭代,并且我认为这是我最终尝试以更高性能的方式进行此工作。

最终,我正在寻求有关如何设置线程环境以在单独的线程上运行Box2D模拟然后在AS3中进行状态轮询的帮助。

方法:

  • 蛮力:

  • 在这种方法中,我只需从AS3调用C,并告诉它创建一个世界,然后将其传递给它以添加到该世界中。在AS3中的每一帧中,我都叫C来告诉世界Step,然后遍历World中的所有物体,获取它们的位置和旋转度,将它们转换为actionscript对象,并将它们放入actionscript数组中,然后将其发送回AS3。到达那里后,我遍历返回的数组,并将这些位置和旋转值分配给我的 Sprite ,以便它们在视觉上进行更新。

    结果实际上是相当不错的,在帧率下降之前添加了约116个盒子。与纯AS3实现中的30个框相比。请注意,这些统计信息处于“调试”模式。在 Release模式下,它们都可以容纳约120个盒子。 AS3实现与 native 扩展实现之间几乎没有区别。
  • ByteArray共享

  • 为了提高性能,我决定尝试限制在C和AS3之间编码的数据量是一个好主意。 ANE的支持共享一个字节数组的内存空间,因此我将在AS3中创建的ByteArray发送给C,让C简单地更新ByteArray。这使我们不必在C中构造AS3对象并将其传递回去。 AS3的每个帧都只需要遍历其ByteArray并查看C写入其中的内容,然后将这些值分配给sprite以设置视觉状态。

    可悲的是,这里的结果差不多。改进只是微不足道的。
  • 来自C的直接对象设置

  • ANE的另一项功能是设置位于AS3中的对象的属性。从这个意义上讲,我的目标是消除将数据传递回AS3的开销,遍历主体以在C中收集数据以及遍历AS3来分配值的开销。我直接修改了Box2D代码,以便在更改其值时将新的x,y旋转值直接写在相应的Sprite上。

    在调用非常少的对象的情况下,结果令人惊讶,因为设置这些属性的调用时间不到一毫秒。问题在于,它线性缩放,大约有90个左右的对象,开销过大,事情开始放慢速度。
  • 线程

  • 在这一点上,我有些困惑。编码数据会产生开销,C中需要迭代和构造要返回的数据,而在AS3中则需要进行迭代以将值分配给Sprite的开销。

    显然,需要进行权衡,因此我目前的解决方案是目前我能想到的最好的解决方案。

    在AS3端,您调用C来创建您的世界,调用来向该世界添加一个框,并调用来告诉C您想要刷新数据。在AS3中创建框时,它们会获得唯一的ID,并将它们存储在字典中,且键为ID。

    在C端,创建了世界,并生成了一个新的pthread来执行步骤。本质上是在另一个线程上模拟世界。步骤完成后,它将组装所有数据并将其写入 double 数组。然后它一次又一次地这样做。它只是在它自己的线程上永久地永远模拟。

    当我们调用C添加一个新框时,我需要创建一个新框并将其添加到该世界中。由于世界步步迈进,这可能会导致问题,这意味着我需要使用互斥量。

    当我们调用以在AIR中刷新值时,同样的事情,我想从double数组中进行一次memcpy转换为AS3字节数组,然后循环遍历字节数组以在视觉上设置值。

    互斥锁给我带来了麻烦,所以我基本上实现了我自己的,您可以在下面看到...并 mock :)

    但是它确实起作用,只是速度不如我想要的那样快。在90左右,我们再次减速。

    任何人有任何想法或指示吗?不胜感激!

    C代码

    解析器正在运行,所以我将其粘贴在这里:
    http://pastebin.com/eBQGuGJX

    AS3代码

    解析器也是如此。我只包括了处理AS3中每个帧的相关方法。
    http://pastebin.com/R1Qs2Tyt

    最佳答案

    我忘了我有这个问题。幸运的是我已经弄清楚了。

    首先,过度使用互斥锁的想法是不必要的。

    由于我们在Flash中运行,因此所有内容都在主线程中运行。这意味着对于每个“帧”闪存, native 都将处理任何媒体,然后处理我们编写的客户端代码,然后实际呈现到屏幕,并最终在必要时进行任何垃圾回收。

    实际上,我并不需要永久地进行物理模拟,只需要使它比我的客户端代码领先一步即可。

    因此,现在发生的情况是,当客户端调用ANE设置环境时,它创建了一个模拟世界的新线程,并立即返回到Flash。 Flash将继续执行其工作,以执行其余的客户端代码,然后进行渲染,然后进行GC。

    然后,在Flash中的每个帧上,我们可以简单地调用ANE来检索结果。在模拟线程尚未完成的情况下,我们通过联接等待,提取值并将其返回给Flash。在返回类(class)之前,请确保为下一步生成另一个线程。

    通过这种方式,我们可以最大程度地提高效率,因为仿真是在Flash忙于执行其他我们无法控制的事情(例如渲染和GC)时进行的。

    好消息是这种方法的性能几乎翻了一番。从同步纯AS3实现中的大约90个框到线程化ANE方法中的大约170个框。

    瓶颈最终成为通过ANE返回的数据并将这些值分配给Display Objects的迭代。

    我希望这对正在寻找类似内容的其他人有所帮助。我将在4月底在FITC多伦多发表有关此事的演讲,以便那时我可以发布更多的信息和 Material 。

    http://www.fitc.ca/events/presentations/presentation.cfm?event=124&presentation_id=1973

    关于multithreading - 用pthread线程Box2D,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9527423/

    10-10 21:14