【问题标题】:NDK vs JAVA performance [closed]NDK 与 JAVA 性能 [关闭]
【发布时间】:2013-12-01 05:21:18
【问题描述】:

是否有人假设使用 NDK 的 C 代码与 java 代码具有相同的计算速度会有多快?(如果有的话)

假设我在 Java 代码中在 Y 秒内进行 X 计算(相同的计算)。
通过 NDK 中的 C 代码,我可以在同一 Y 秒内进行多少次 X 计算?
1.2 ?
2.7 ?
你猜数字吗?

假设计算是 B=L/A +C/D(所有 X 计算都相同)。

编辑:

我为什么要问这个?
因为我考虑将我的 java 处理相机帧移动到 C 代码。以获得更大的分辨率机会

【问题讨论】:

    标签: java android c android-ndk


    【解决方案1】:

    您可能不会从任何人那里得到明确的答案。这些问题远比看起来复杂得多。

    使用 NDK 或 SDK 在 OpenGL 中放置相同数量的多边形是没有问题的。毕竟这只是相同的 OpenGL 调用。渲染多边形(批量)的时间比函数调用开销的时间要长几个数量级。所以它通常是完全可以忽略的。

    但一旦应用程序变得更复杂并执行一些重要的计算(人工智能、场景图管理、剔除、图像处理、数字运算等),原生版本通常会快得多。

    还有一件事:除了当前没有 JIT 编译的根本问题。 当前的 dalvikvm 及其编译器似乎非常基础,没有做任何优化——甚至不是最基本的优化!

    有这个(非常好的)视频:Google I/O 2009 - 为 Android 编写实时游戏 在我看到它之后,我很清楚我一定会在 NDK 中使用 C++。

    例如:他在谈论函数调用的开销“不要使用函数调用”。 ...所以是的,我们回到了 1970 年之前,开始谈论结构化编程的成本以及仅使用全局变量和 goto 的性能优势。

    垃圾收集对于游戏来说是一个真正的问题。因此,您将花费大量时间思考如何避免它。即使格式化字符串也会创建新对象。所以有一些提示,比如:不要显示 FPS! 说真的,如果您了解 C++,那么使用 new 和 delete 管理内存可能比调整架构以减少/避免垃圾收集更容易。

    如果你想编写一个不平凡的实时游戏,你似乎失去了 Java 的所有优势。不要使用 Getter 和 Setter,不要使用函数调用。避免任何抽象等。严重吗?

    但回到你的问题:NDK 与 SDK 的性能优势可以是 0-10000% 之间的任何值。这一切都取决于。

    【讨论】:

    • 感谢您的回答。但我试图做的只是对相机帧的基本计算——不是游戏,而是视频。只需操纵帧并使用 FFmpeg 对其进行编码。所以我考虑在哪里应该编写“操纵”代码。现在我使用 java-所以我考虑将其移至 C 以获得更好的性能
    • “不做任何优化” ...见stackoverflow.com/questions/4912695/…。答案是 2.5 岁,但 Dalvik 从那时起就没有真正改变过。
    【解决方案2】:

    由于没有人愿意接触这个话题,既然不考虑认真回答它,我就试试吧:

    • Java 编译成字节码,字节码通过 JIT 编译成原生代码。
    • C 直接编译为本机代码。

    不同之处在于额外的编译步骤,理论上 java 应该比 C 编译器做得更好,原因如下:

    • Java 可以将统计计算插入到生成的本机代码中,然后在一段时间后重新生成它,以针对代码中的当前运行时路径对其进行优化!

    最后一点听起来很棒,但是 java 确实有一些权衡:

    • 需要运行 GC 来清理内存
    • 它可能根本不是 JIT 代码

    GC 复制活动对象并抛出所有死对象,因为 GC 不需要为死对象做任何事情,只为活对象做任何事情,理论上 GC 比对象的正常 malloc/free 循环更快。

    但是,大多数 Java 拥护者忘记了一件事情,那就是在编写 C 代码时,您必须对每个对象实例进行 malloc/free。您可以重用内存,您可以 malloc up 内存块和释放包含以下内容的内存块一次处理数千个临时对象。

    随着 Java 的大堆,GC 时间增加,增加了停顿时间。在某些软件中,GC 清理周期中的停顿时间是完全可以的,而在其他软件中,它会导致致命错误。尝试在 GC 发生时让您的软件在定义的毫秒数内做出响应,您就会明白我在说什么。

    在某些极端情况下,JIT 也可能选择根本不 JIT 代码。如果我没记错的话,当 JITed 方法很大,8K 时,就会发生这种情况。非 JITed 方法的运行时损失在 20000% 范围内(慢 200 倍,即至少在我们的客户中是这样)。当 JVM 的 CodeCache 开始变满时,JIT 也会被关闭(如果不断地将新类加载到 JVM 中,这可能会发生,也可能发生在客户站点)。 在某一时刻,JIT 统计数据还将一台 128 核机器上的并发性降低到基本上是单核性能。

    在 Java 中,JIT 有特定的时间来将字节码编译为本机代码,不能为 JIT 花费所有 CPU 资源,因为它与代码并行运行你的程序的实际工作。在 C 中,只要编译器需要吐出它认为最优化的代码,编译器就可以运行。 它对执行时间没有影响,在 Java 中它有。

    我说的是真的:

    • Java 可以为您提供更多功能,但它的性能并不总是由您决定。
    • C 为您提供的功能较少,但它的性能取决于您。

    所以回答你的问题:

    • 不选择 C ​​而不是 Java 不会使您的程序更快

    如果您只对预分配缓冲区进行简单的数学运算,那么 Java 和 C 编译器应该会输出大约相同的代码。

    【讨论】:

    • 非常感谢您的详细评论。我会仔细阅读。
    • 所以据我了解,如果我计算这个表达式:arr[i]=arr1[i]/arr2[2] 2 种情况下需要相同的时间吗?
    • 这个答案很好,但它与android无关。如果android允许你用c++绕过java,应该说些什么。确实如此。 stackoverflow.com/questions/8922608/…
    • 添加到这个。 java 不适合并行编程,因为 oop 不适合并行编程。 java也没有像c++一样好的元编程
    • 这个答案非常简单。猜猜看,您的 CPU 还会在分支预测表中累积统计信息,并且您的代码也会在运行时得到优化。更不用说您的 C 结构保证小于 Java 对象等效项,因此您可以更好地利用缓存一致性。这个答案没有用真实数据支持任何声明,也不能说明整个故事。我投反对票
    猜你喜欢
    • 2011-08-04
    • 2013-11-27
    • 2015-07-08
    • 1970-01-01
    • 1970-01-01
    • 2013-01-05
    • 1970-01-01
    • 2011-01-29
    • 2012-10-20
    相关资源
    最近更新 更多