使用JNI,或不使用JNI(Android性能)

use*_*709 11 java-native-interface android collision-detection

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

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

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

以上问题是我主要关心的问题和我的问题.我已经确定以下两个原因是使用JNI的其他积极结果.但是,仅仅说服我将代码移植到C++是不够的.

  • 这将使代码更清晰.由于大多数碰撞检测都是某种向量数学,因此能够使用重载运算符而不是在Java中使用更冗长的向量类更为清晰.

  • 内存管理会更简单.你说比较简单吗?好吧,这是一款游戏,因此垃圾收集器运行不受欢迎,因为如果GC不断中断清理,GC最终可能会破坏游戏的性能.在CI中不必担心垃圾收集器,所以我可以避免使用临时静态变量在Java中做的所有丑陋的事情,并且只依赖于C++的旧旧堆栈内存

这问题可能是啰嗦,我想我已经涵盖了所有的观点.鉴于此信息,是否值得将我的代码从Java移植到C++并使用JNI访问它(出于提高性能的原因)?此外,有没有办法衡量或估计潜在的性能增益?

编辑:

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

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

另外,我只使用了Eigen数学库,而不是滚动我自己的矢量类.我不确定这会对性能有多大的影响,但至少,它为我节省了开发自己(效率较低)的矢量类的时间.

另一个经验教训是过度记录对性能不利(jic并不明显).

Jav*_*ave 5

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

在第二个链接中写了以下内容:

本机代码不一定比 Java 更有效。一方面,Java 原生转换会产生相关成本,而 JIT 无法跨越这些边界进行优化。如果您要分配本机资源(本机堆上的内存、文件描述符或其他任何内容),则安排及时收集这些资源可能会困难得多。您还需要为您希望在其上运行的每个架构编译代码(而不是依赖它具有 JIT)。您甚至可能需要为您认为相同的架构编译多个版本:G1 中为 ARM 处理器编译的本机代码无法充分利用 Nexus One 中的 ARM,而 Nexus One 中为 ARM 编译的代码不会在 G1 的 ARM 上运行。

当您拥有想要移植到 Android 的现有本机代码库时,本机代码主要有用,而不是用于“加速”Java 应用程序的部分。