要使用JNI,还是不要使用JNI(Android性能)

我只是在我正在开发的Android游戏中添加了一些计算量很大的代码。 有问题的代码是碰撞检测例程的集合,经常被调用(每次迭代的游戏循环),并进行大量的计算。 我觉得我的碰撞检测实现相当完善,而且我可以在Java中使用它。

我一直在使用Traceview来分析代码,而这个新的碰撞检测代码在一定程度上使我的游戏逻辑的持续时间翻了一番。 这显然是一个问题,因为对于某些设备来说,这种性能下降可能会使我的游戏从可玩的状态变为无法玩的状态。

我一直在考虑不同的方法来优化这个代码,我想知道如果通过将代码移动到C ++并使用JNI访问它,是否会获得显着的性能节省?

上述问题是我主要关心的问题,也是我提出的理由。 我确定下面两个原因是使用JNI的其他积极结果。 但是,说服我将代码移植到C ++是不够的。

  • 这将使代码更清洁。 由于大多数碰撞检测都是某种向量math,所以能够使用重载运算符而不是在Java中使用一些更详细的向量类要清楚得多。

  • 内存pipe理将会更简单。 你说得更简单? 那么,这是一个游戏,所以垃圾收集器的运行是不受欢迎的,因为如果GC经常要中断清理,GC可能会毁了你的游戏的性能。 在CI中,不用担心垃圾收集器,所以我可以避免在Java中使用临时静态variables所做的所有丑陋的事情,只依靠C ++的旧堆栈内存

这个问题可能是啰嗦,我认为我涵盖了所有的观点。 鉴于这些信息,是否值得将我的代码从Java移植到C ++并使用JNI访问它(出于提高性能的原因)? 另外,有没有一种方法来衡量或估计潜在的性能增益?

编辑:

所以我做到了。 结果? 从TraceView的angular度来看,我的碰撞检测程序速度提高了6倍。

到达那里并不容易。 除了做JNI舞之外,我还不得不做一些我没想到的优化。 主要是使用直接分配的float缓冲区来将数据从Java传递到本地。 我最初的尝试只是使用浮点数组来保存有问题的数据,因为从Java到C ++的转换更自然,但实际上实际上很慢。 直接缓冲区完全侧面性能问题与java和本地之间的数组复制,留给我一个6倍的凹凸。

另外,我只是使用了Eigenmath库,而不是滚动我自己的vector类。 我不确定这对性能有多大的影响,但是至less为我节省了开发我自己的(低效率)vector类的时间。

另一个教训是,过度采伐对性能不利(jic不明显)。

Solutions Collecting From Web of "要使用JNI,还是不要使用JNI(Android性能)"

不是真的直接回答你的问题,但以下链接可能对你有用:

  • Android开发人员,JNI技巧。
  • Android开发人员,devise性能

在第二个链接中写着:

本机代码不一定比Java更高效。 首先,与Java本地转换相关的成本,JIT无法跨越这些边界进行优化。 如果您正在分配本地资源(本机堆内存,文件描述符或其他),那么安排及时收集这些资源将会非常困难。 您还需要编译您希望运行的每个架构的代码(而不是依赖于它具有JIT)。 您甚至可能需要编译多个版本以用于您认为具有相同体系结构的版本:为G1中的ARM处理器编译的本机代码无法充分利用Nexus One中的ARM,以及在Nexus One中为ARM编译的代码不会在G1上运行在ARM上。

当你有一个你想要移植到Android的现有的本地代码库时,原生代码是非常有用的,而不是为了“加快”Java应用程序的某些部分。

如果你还处于游戏开发的早期阶段,你可以考虑使用一个游戏引擎,它提供了一个很好的碰撞检测机制,比如Libgdx,它在box2d碰撞检测方面做得相当不错。