【问题标题】:To use the JNI, or not to use the JNI (Android performance)使用 JNI,或者不使用 JNI(Android 性能)
【发布时间】: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


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 我知道 JNI 调用的开销。但我只知道它存在,我不确定它是否会否定或可能恶化我从使用本机代码中获得的任何性能提升。但是,我对第一段的后半部分更好奇。如果我使用一些本机代码,我是否必须为存在的“不同架构”编译它?我什至如何开始找到我需要编译的架构?这样做会不会导致我的应用出现错误,或者它只是没有得到应有的优化?
    • 最后,随着我对该主题的深入研究,我遇到了一个有趣的性能测试,该测试考虑了 Java/native 与定点/浮点运算的 imapct。在这些计算中使用本机代码的好处是一个很好的改进。我发现这些基准是相关的,因为我希望本地化的代码正在执行大量浮点计算。 badlogicgames.com/wordpress/?p=71 编辑:这可能更针对第一代 Android 设备。这些设备每天都变得越来越不重要,所以这篇文章可能没有我想象的那么重要。
    • 老实说,我不知道“为不同架构编译”部分,因为我通常不使用 jni。关于浮点运算,我发布的第一个链接也有关于浮点运算的部分:“根据经验,浮点在 Android 设备上比整数慢大约 2 倍。这在无 FPU 的 JIT 上是正确的-less G1 和带有 FPU 和 JIT 的 Nexus One。(当然,这两个设备之间的绝对速度差异大约是算术运算的 10 倍。)"
    【解决方案2】:

    如果您还处于游戏开发的早期阶段,您可以考虑使用提供良好碰撞检测机制的游戏引擎,例如 Libgdx,它在 box2d 碰撞检测方面做得相当好。

    【讨论】:

    • 这对很多开发者来说是一个很好的建议。我决定编写自己的引擎有两个原因:它是 3 维的(许多 android 游戏引擎仅适用于 2d 游戏),而且我发现设计和开发大型系统的过程非常有趣。引擎在这一点上相当大,超过 10k 行代码,并且在许多地方都是数据驱动的。一旦我完成了核心功能的开发,我很可能会将它发布给其他人使用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-06
    • 2013-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多