7

解释器做了很多额外的工作,因此它们最终比本地机器代码慢得多是可以理解的。但是 C# 或 Java 等语言有 JIT 编译器,据说可以编译为平台本机机器代码。

然而,根据似乎足够合法的基准,在大多数情况下,仍然比 C/C++ 慢 2-4 倍?当然,我的意思是与同样优化的 C/C++ 代码相比。我很清楚 JIT 编译的优化优势以及它们生成比优化不佳的 C+C++ 更快的代码的能力。

在所有关于 Java 内存分配有多好的噪音之后,为什么会有如此可怕的内存使用?2 倍到 50 倍,平均而言,在该特定基准套件中使用的内存增加了大约 30 倍,这没什么好打喷嚏的……

请注意,我不想开始 WAR,我询问的是定义这些性能和效率数据的技术细节。

4

3 回答 3

7

产生差异的一些原因;

  • JIT 编译器大多快速编译并跳过一些需要更长时间才能找到的优化。

  • VM 通常会强制执行安全性,这会减慢执行速度。例如,数组访问总是在 .Net 中检查边界,除非保证在正确的范围内

  • 在 C++ 中使用 SSE(如果适用,对性能很有帮助)很容易,而在当前 VM 中使用 SSE 很困难

  • 与 VM 相比,C++ 的性能比其他方面更重要

  • 虚拟机通常会在返回操作系统之前保留未使用的内存一段时间,似乎“使用”更多内存。

  • 一些 VM 生成值类型的对象,例如 int/ulong .. 增加对象内存开销

  • 一些 VM 的自动对齐数据结构会大量浪费内存(以提高性能)

  • 一些 VM 将布尔值实现为 int(4 字节),很少关注内存保护。

于 2012-08-09T11:52:03.517 回答
0

但是 C# 或 Java 等语言有 JIT 编译器,据说可以编译为平台本机机器代码。

最后,口译员还必须翻译成机器代码。但是为了更好的启动和执行时间,JITters 花费更少的精力来编译和优化。从用户的角度来看,在编译上浪费时间会使感知的性能更差,因此只有在AoT 编译器中只执行一次时才有可能。

他们还必须监视编译结果以重新编译和优化热点,或者对很少使用的路径进行反优化。然后他们不得不偶尔触发 GC。这些比正常编译的二进制文件花费更多时间。此外,JITter 和 JITted 程序的大量内存使用可能意味着缓存使用效率较低,这反过来也会降低性能

有关内存使用的更多信息,您可以在此处参考

Java 内存使用量比 C++ 的内存使用量大得多,因为:

  • 在 Java 中,每个对象有 8 字节的开销,每个数组有 12 字节的开销(32 位;在 64 位 Java 中是两倍)。如果对象的大小不是 8 字节的倍数,则向上舍入到下一个 8 的倍数。这意味着包含单字节字段的对象占用 16 字节,并且需要 4 字节的引用。请注意,C++ 还为每个声明虚函数的对象分配一个指针(通常为 4 或 8 个字节)。
  • Java 库的某些部分必须在程序执行之前加载(至少是程序“在后台”使用的类)。 [60] 这导致小型应用程序的显着内存开销[需要引用]。
  • Java 二进制和本机重新编译通常都在内存中。
  • 虚拟机本身会消耗大量内存。
  • 在 Java 中,使用对已分配的 B 和 C 实例的引用创建复合对象(使用 B 和 C 的实例的类 A)。在 C++ 中,当 B 和 C 的实例时,可以避免这些类型引用的内存和性能成本/ 或 C 存在于 A 中。
  • 缺乏地址算法使得创建内存高效的容器(例如紧密间隔的结构和 XOR 链表)成为不可能。

在大多数情况下,由于 Java 的虚拟机、类加载和自动调整内存大小的开销很大,C++ 应用程序将比等效的 Java 应用程序消耗更少的内存。对于内存是在语言和运行时环境之间进行选择的关键因素的应用程序,需要进行成本/收益分析。

还应该记住,使用垃圾收集器的程序可能需要使用显式内存管理的程序的五倍内存才能达到相同的性能。

于 2013-08-03T14:32:09.043 回答
-1

为什么如此可怕的内存使用?2 倍到 50 倍,平均而言,在该特定基准套件中使用的内存增加了大约 30 倍,这没什么好打喷嚏的……

请参阅https://softwareengineering.stackexchange.com/a/189552

于 2016-05-26T23:19:01.083 回答