Java不是一种解释型语言,也没有几个版本。Java 字节码是动态 JIT 的。(从技术上讲,它仍然解释一些代码,但是任何在性能方面重要的东西都会被JIT'ed)
至于性能,到底是什么让你疯狂地认为“有一个开销基线”?没有。从来没有,也永远不会有。不是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'ing内存块来回收。在C++析构函数必须始终执行,几乎每个对象都有一个)
GC的主要问题是,虽然平均而言垃圾回收器的性能更好,但您无法控制何时承担性能成本。手动内存管理可确保线程在等待清理内存时不会停止。垃圾回收器几乎可以随时决定暂停该过程并清理内存。在几乎所有情况下,这都足够快,没有问题,但对于重要的实时内容,这是一个问题。
(另一个问题是你失去了一点表现力。在C++中,RAII用于管理各种资源。在Java中,你不能使用RAII。相反,GC为您处理内存,对于所有其他资源,您被搞砸了,并且必须自己做很多尝试/最终块。RAII没有理由不能用GC的语言实现,但它在Java或C#中都不可用)
从 Java 进行系统调用的开销是多少?例如,创建一个 Socket 对象,而不是 C socket API。
大致相同。为什么会有所不同?当然,Java必须调用相关的操作系统服务和API,所以有一点点开销,但实际上你可能不会注意到。
最后,我记得在某处读到JVM实现是单线程的。如果这是真的(我对此持怀疑态度),这是否意味着Java线程真的不是真正的线程?一般来说,Java线程是否对应于内核提供的底层线程?Java应用程序是否像本机应用程序从多核/多个CPU中受益一样?
Java可以使用多个线程,是的。JVM本身可能是单线程的(从某种意义上说,所有的JVM服务都在同一线程上运行),我不知道这一点。但是,您的 Java 应用程序可以使用任意数量的线程,并且它们映射到操作系统线程,并将使用多个内核。