【发布时间】:2012-02-01 19:27:51
【问题描述】:
我刚刚在我正在开发的 Android 游戏中添加了一些计算量大的代码。有问题的代码是一组碰撞检测例程,这些例程经常被调用(游戏循环的每次迭代)并进行大量计算。我觉得我的碰撞检测实现开发得相当好,并且在 Java 中实现的速度相当快。
我一直在使用Traceview 来分析代码,而这段新的碰撞检测代码无疑将我的游戏逻辑的持续时间加倍了。这显然是一个问题,因为对于某些设备,这种性能下降可能会使我的游戏从可玩状态变为不可玩状态。
我一直在考虑优化此代码的不同方法,我想知道是否通过将代码移动到 C++ 并使用 JNI 访问它,我是否会获得一些明显的性能节省?
上述问题是我主要关心的问题,也是我提出问题的原因。我已经确定以下两个原因将是使用 JNI 的其他积极结果。但是,仅仅说服我将代码移植到 C++ 是不够的。
这将使代码更清晰。由于大多数碰撞检测都是某种矢量数学,因此能够使用重载运算符而不是在 Java 中使用一些更冗长的矢量类要干净得多。
内存管理会更简单。你说更简单?好吧,这是一个游戏,所以垃圾收集器运行是不受欢迎的,因为如果 GC 不断地中断清理,它最终可能会破坏你的游戏性能。在 C 中我不必担心垃圾收集器,因此我可以避免我在 Java 中使用临时静态变量所做的所有丑陋的事情,而只依赖于 C++ 的良好旧堆栈内存
尽管这个问题可能很啰嗦,但我想我已经涵盖了所有观点。鉴于此信息,是否值得将我的代码从 Java 移植到 C++ 并使用 JNI 访问它(出于提高性能的原因)?另外,有没有办法衡量或估计潜在的性能提升?
编辑:
所以我做到了。结果?从 TraceView 的角度来看,我的碰撞检测程序的速度提高了 6 倍。
虽然到达那里并不容易。除了必须跳 JNI 舞之外,我还必须进行一些我没想到的优化。主要是使用直接分配的浮点缓冲区将数据从 Java 传递到本机。我最初的尝试只是使用一个浮点数组来保存有问题的数据,因为从 Java 到 C++ 的转换更自然,但这真的很慢。直接缓冲区完全回避了 java 和本机之间数组复制的性能问题,并给我留下了 6 倍的冲击。
另外,我没有使用自己的向量类,而是使用了 Eigen 数学库。我不确定这对性能有多大影响,但至少它为我节省了开发自己的(效率较低的)向量类的时间。
另一个教训是过多的日志记录不利于性能(jic 并不明显)。
【问题讨论】:
标签: android java-native-interface collision-detection