Java 不是一种解释性语言,并且没有几个版本。 Java 字节码是即时 JIT 的。 (从技术上讲,它仍然会解释一些代码,但任何与性能有关的东西都会被 JIT 处理)
至于性能,究竟是什么让您产生了“开销有基线”的疯狂想法?没有。从来没有,也永远不会。不在 C++ 和 Java 之间,也不在 Python 和 Javascript 或 任何 其他两种语言之间。有些事情你的特定版本的 JVM 会比你的特定 C++ 编译器做得更快,而你的特定 C++ 编译器会比你的特定 JVM 做得更好。
因此,您选择语言的“开销”完全取决于 1)您希望代码做什么,以及 2)您如何编写代码。
如果你把一个 Java 程序翻译成 C++,结果几乎肯定会运行得更慢。
如果你将一个 C++ 程序翻译成 Java,它的运行速度也会变慢。
不是因为一种语言比另一种语言“更快”,而是因为原始程序是为一种语言编写的,并且经过量身定制以在那种语言中运行良好。任何将其翻译成另一种语言的尝试都将失去这一优势。您最终会得到一个 C++ 风格的 Java 程序,它不会在 JVM 上高效运行,或者一个 Java 风格的 C++ 程序,它也将运行非常糟糕。
两种语言规范都不包含“并且结果必须至少比语言 y 慢 x%”的子句。您的 C++ 编译器和 JVM 都尽最大努力使事情进展顺利。
然后您今天看到的性能特征可能会在明天发生变化。语言没有速度。
但要回答您的具体问题:
使用解释器时必须有一些开销基线。是否有一些一般的经验法则要记住? 10% 15%?我偶尔读过一篇博客,说 Java 代码几乎和本机代码一样快,但我可能有偏见。
如上所述,这取决于。对于许多常见任务,您通常不会看到超过百分之几的差异。对于某些用例,您会看到更大的差异(无论哪种方式。两种语言在性能方面都有优势。有一些与 JVM 相关的开销,但也有巨大的优化机会,尤其是垃圾收集器)
JVM 垃圾收集器是否会显着增加运行时性能的开销?我知道 Cocoa 应用程序已经开始使用垃圾收集模型,我同意它使编程变得更简单,但代价是什么?
基本上没有。平均而言,垃圾收集器比手动内存管理快,原因有很多:
- 在托管堆上,动态分配可以更快地完成
- 可以以可忽略不计的摊销成本处理共享所有权,在本机语言中,您必须使用非常昂贵的引用计数
- 在某些情况下,对象销毁也得到了极大的简化(大多数 Java 对象可以通过对内存块进行 GC 来回收。在 C++ 中,必须始终执行析构函数,并且几乎每个对象都有一)
GC 的主要问题是,虽然平均而言垃圾收集器的性能更好,但您会失去对 when 的一些控制以承担性能成本。手动内存管理可确保您的线程在等待清理内存时永远不会停止。垃圾收集器几乎可以在任何时候决定暂停进程并清理内存。在几乎所有情况下,这都足够快,不会有问题,但对于重要的实时数据来说,这是一个问题。
(另一个问题是你失去了一点表达能力。在 C++ 中,RAII 用于管理各种资源。在 Java 中,你不能使用 RAII。而是 GC 为你处理内存,并且为所有其他资源,你搞砸了,必须自己做很多尝试/最终块。没有理由不能用 GC 语言实现 RAII,但它在 Java 或 C# 中都不可用)
从 Java 进行系统调用的开销是多少?例如创建一个 Socket 对象,而不是 C 套接字 API。
大致相同。为什么会不一样?当然,Java 必须调用相关的 OS 服务和 API,因此会有一点点开销,但您可能不会注意到。
最后,我记得在某处读到 JVM 实现是单线程的。如果这是真的(我对此表示怀疑),这是否意味着 Java 线程真的不是真正的线程?一般来说,Java 线程是否对应于内核提供的底层线程? Java 应用程序是否像本机应用程序从多核/多 CPU 中受益一样?
Java 可以使用多个线程,是的。 JVM 本身 可能是单线程的(从某种意义上说,所有的 JVM 服务都运行在同一个线程上),我对此一无所知。但是您的 Java 应用程序可以使用任意数量的线程,并且它们被映射到操作系统线程并且将使用多个内核。