任何人都可以量化C ++和Java之间的性能差异吗?

Java在JIT之前最初很慢,但今天的性能非常接近C ++。 我想知道是否有人在两种语言之间进行了可衡量的性能比较? 与C ++相比,Java在哪里不足? Java为开发人员提供了许多生产力提升,因此他们可以更快地编写应用程序,因为垃圾大学,缺乏指针等。例如,如果用100写的话,可以更快,更可靠地开发Firefox,Webkit和Open Office等应用程序。 %Java,可能是2倍,但开发人员仍然出于性能原因选择C / C ++。 有人可以certificateJava不能像我提到的那样为应用程序执行C ++。

我只想补充一点,在C ++中仍然有很多应用程序工作是有原因的。 这不仅仅是一个主观问题。 具有较高抽象级别的语言经常会产生性能损失。 如果没有这种惩罚,我们都会用更高级别的语言进行编程。 Java与C ++相比还在哪里支付? 请明确点。

对于许多单独的代码构造,JIT编译器可以更快,因为它们可以利用代码的运行时分析。

例如,VonC在回答这个问题时提到了所有对象的堆分配。 实际上并非如此:如果可以通过转义分析certificate对象的引用不会超过堆栈帧,则JIT可以在堆栈上分配对象。 通过这种方式,编译器可以获得堆栈分配的性能优势,同时程序员可以放心假设GC堆分配的安全性。

类似地,Uri提到了虚函数(在大多数非C ++语言中称为虚方法)。 这是另一种情况,JIT编译器具有几乎永远不可用于提前(AOT)编译器的优点:JIT可以插入内联廉价类型检查(解除引用的字比较)并实际内联虚拟方法调用,如果特定的呼叫站点恰好是单态的(即实际类型在实践中总是相同的)。 事实certificate,高达95%的虚拟方法调用在实践中都是单态的,所以这可能是一个很大的胜利 – 而且这是AOT编译器难以利用的一个胜利,因为运行时代码加载可能会改变运行时特性动态。

语言没有速度。 Java或C ++语言规范都没有指定“并且必须编译程序以使其高效”。

每种语言都指定了程序必须要做的事情列表,或者至少看起来要做的事情 ,这在某些情况下会对程序的效率设置上限,但通常,聪明的编译器可以在单个程序中忽略这些规则,因为重要的是程序的行为就像规范已被遵循一样。 函数可以内联,堆数据可以移动到堆栈等等。

程序的性能取决于三件事:编译器,底层平台/硬件和程序代码本身。

不是“语言”。 你得到的最接近的是编译器。

有很好的理由说明为什么这两种语言比另一种语言更快。 C ++减少了可能会减慢程序执行速度的承诺,但是Java是JIT,这意味着它可能会利用运行时信息来优化代码,C ++不能轻易做到……然后,无处可去该规范是否说C ++ 不能被jit’ed。 就像我相信也有Java编译器生成本机代码而不是JVM字节码。

只有你有一台运行的特定计算机,每种语言的特定编译器,以及每种语言的程序的特定实现,你的问题才有意义, 在这种情况下你可以运行两者来查看哪个是最快的

垃圾收集是另一个很好的例子。 当然,垃圾收集意味着一些开销,但它也可以实现一些重要的快捷方式。 堆栈分配在Java或.NET等托管语言中非常便宜, 因为它是经过管理和垃圾回收的。 在C ++中,它是……未指定的,当然,但在实践中,通常非常慢,因为操作系统必须遍历堆以在或多或少碎片化的内存空间中找到一个空闲的内存块。 哪个最快? 取决于操作系统。 取决于编译器。 取决于源代码。

源代码也有很大的不同。 如果您使用Java程序并天真地将其移植到C ++,它将像垃圾一样执行。 C ++不能很好地处理虚拟function,并且通常可以使用更好的替代方案。 在C ++中,堆分配可能非常慢,所以再次,天真地重新实现Java程序将是非常低效的。 当采取相反的方式时也是如此。 如果直接移植到Java,许多C ++习语会不必要地慢。 因此,即使您已经确定了一个平台和一个编译器,您如何比较程序的性能? 要将它转换为编译器,你必须编写它的两个实现,然后它不再是同一个程序。

但是,我认为可以说,在大多数现代硬件上,使用现代Java编译器和现代C ++编译器,大多数程序都可以实现非常高效,当然也足够快。 但只有你理解了你正在使用的语言,并遵守其规则。 如果你试图用C ++编写Java代码,那么Java将神奇地变得更加高效,反之亦然。

我想对你的问题最简洁的答案是“不。没有人可以量化C ++和Java之间的性能差异”;)

要完成Pax和Uri的答案,这里有一些最近的基准:

  • 性能比较 – C ++ / Java / Python / Ruby / Jython / JRuby / Groovy
  • Java性能(维基百科)

如上所述,这是两种截然不同的语言,有些人确信Java会比C ++慢,原因如下:

  • 所有对象的堆分配(甚至像迭代器那样的小对象)
  • 很多动态铸件
  • 增加内存使用量

[幽默]

“Java是高性能的。通过高性能我们意味着足够。足够我们意味着缓慢。” 兔子先生

如评论中的dribeas所述,堆分配不是一个好的论据。
这个“ 城市表演传说,重访 ”提到:

“垃圾收集永远不会像直接内存管理那样高效。” 而且,在某种程度上,这些陈述是正确的 – 动态内存管理不是那么快 – 它通常要快得多
malloc / free方法一次处理一个内存块,而垃圾收集方法倾向于大批量处理内存管理,从而产生更多的优化机会(以可预测性的某些损失为代价)。

还有另一个板凳: 枪战

在许多方面,这就像比较苹果和橙子。

C ++建立在你不为任何不使用的东西付费的概念之上。 如果您自己管理内存,如果您不使用虚拟function等。

Java并没有给你这种自由。 它为您提供了您可能不想要的function。 对于您可能想要自己分配内存的所有内容,您将不得不为所有内容使用堆对象,因此您将受到垃圾收集的影响。

一旦你开始讨论GUI,这是一个更难的比较,因为不同的UI框架和工具包有不同的性能问题。 例如,Swing / AWT通常比直接为本机OS编写的内容慢。 在C ++中,您很少会找到真正的便携式工具包等。

我认为当开发人员启动openoffice时,Java速度要慢得多,而且UI工具包很慢而且很丑陋。 像Eclipse这样的工具certificate了即使在Java中也可以构建相对优秀的UI,但不可否认,SWT是一个在本机级别执行大量工作的工具包。

许多人忘记了JIT技术可以应用于任何类型的二进制文件,甚至是由C ++编译器生成的二进制文件。 如果您使用类似HP的Dynamo(一种运行可执行文件的模拟器比运行和模拟的本机芯片更快),JIT编译Java的大部分好处对C ++也有效。 运行时分析不是Java的性能优势,而是JIT编译的一般性能。

对我来说,这个问题有点像红色鲱鱼(也许不是故意的)。 这真的是一个错误的问题。

首先要问的问题是这些问题

  1. 什么让我的程序变慢?
  2. 对于我的新计划,关键性能设计考虑因素是什么?

这里有一些很好的’为什么’的问题

  • 是否有太多不必要的I / O?
  • 是否使用了太多内存?
  • 内存分配器是否被打乱(分配太多,细粒度对象太多)
  • 我的程序是否在网络I / O上长时间被阻止
  • 锁在错误的地方

我怀疑你真的需要关注你的程序的性能方面(首都’P’),首先要考虑性能(小’p’)方面。 如果你能够达到语言阻碍的程度,那么就性能而言,你已经做了很好的工作。

对于新代码 – 预先计划性能和效率非常重要。 我总是建议性能和效率与任何其他function(它们都是function)一样对待:就像UI bling或可靠性一样。 当然这取决于很多事情 – 但是当它很重要时,你需要预先计划好:

  • 选择适合数据集和预期缩放的数据结构和算法
  • 适当的基于multithreadingUI的应用程序(UI线程,后台/处理线程)
  • 规划长网络I / O延迟
  • 计划设定目标并预先测量绩效 – 定期进行回归测试
  • 测量内存使用情况 – 内存生长很慢(让japes开始:))
  • 有事件,回调或其他通知机制时不要轮询

我认为这是一个红色鲱鱼的原因是很少有人可以在C ++和Java之间做出选择 – 它们是非常非常不同的语言,具有非常不同的运行时间。 我怀疑是否更常见的是你有其他限制推动你的方式 – 这些将是比语言表现更高阶的因素。 可与现有代码,现有员工的技能和经验等进行计算。

环境也有所不同。 例如,Java几乎永远不会是寡妇客户端(相对于Web)应用程序的正确选择。 相反,原生C ++几乎永远不会成为基于Web的应用程序的选择。 (注意,我是一个Windows家伙 – * nix中的情况可能非常不同)。

我不相信任何人都可以certificateC ++总是比Java快得多,因为你总是可以恢复到JNI以从Java获得本机速度。

例如,参见SWT,它是由IBM构建的图形工具(我认为)意味着取代Swing并提供本机性能和外观。

因此,我认为开发速度比速度快,因为我认为最小开发时间比原始应用程序速度更重要,特别是当我仍然能够达到这个速度时 – 我可以同时拥有Java的易开发性编译语言的速度。

有些要点需要考虑:

  • 如果你有一个更好的C ++编译器,你的代码不会变得更快。 您需要先重新编译它。 如果您获得了更好的JVM,那么所有Java代码都将运行得更快

  • 如果你有一个更好的C ++编译器/ JVM,你会看到执行速度提高10-20%,通常是在极端情况下。 如果您找到更好的算法来实现您的需求,您可以轻松获得1,000%-10,000%的性能,有时甚至更多。

所以今天,如果表现是一个问题,你应该看看这两个事实:

  • 语言用一种算法替换另一种算法有多容易? (又名“重构”)
  • 你能用多快的速度编写代码?

其他任何东西都只是FUD。

我已经在C和Java中实现了对性能敏感的应用程序(物理模拟,财务模型)。 实际情况是,通过改变算法而不是通过调整实现,我总能获得更大的性能提升 – 但实现也很重要。 至于现在,我的观点是Java比C慢(我对C ++中的数字没有那么多经验),但通过仔细调整可以获得很多,而且这种调整在Java中要容易得多,因为你不必处理分段错误,双重释放等.C ++占据了中间地带,因为现代C ++技术(智能指针,模板,STL容器)提供了速度和相对安全性。

与C ++相比,Java在哪里不足?

好问题。 与C ++相比,Java和JVM有两个主要缺陷,使性能瘫痪:

  • 基于类型擦除的generics。

  • 缺乏价值类型。

前者意味着通用代码会导致装箱和拆箱,这会导致大量不必要的分配以及缓存不友好的额外间接级别。

后者意味着程序员不可能打开任意数据结构,如复数(浮点数对),散列表条目(键值对)和顶点数据。

这两个问题相结合,使得无法在Java中实现有效的通用哈希表。 特别是,.NET解决了这两个问题。 例如, Java的通用哈希表可能比.NET Dictionary慢17倍 。

此外,与C ++相比,JVM的FFI非常慢。 我听说只需从Java调用外部C函数就可以花费1000个周期。

使用Java,C#或任何托管编程语言可以更好地构建一些东西。 使用非托管编程语言(如C或C ++)更好地构建其他东西

前一类通常包括“应用程序”,而第二类通常包括“平台”。

在Java中构建FireFox或WebKit不仅仅是简单的愚蠢,而且会使最终产品真正,非常慢,糟糕并为最终用户浪费大量资源。 Open Office可能是Java,C#或SmallTalk的好选择。 但是用Java构建FireFox或WebKit(或C#就此而言)显然是愚蠢的,是失败保证……

对于很多东西,C ++和C的速度会快几个数量级,此外它还会占用一小部分内存。 就是那样子。 只要Java和C#是“托管”编程语言,这将永远不会改变。 也许有一天CPU会如此之快以至于“无关紧要”。 但我对此表示怀疑,因为随着更多CPU的出现,人们倾向于屈服于他们的需求……

如果你想构建浏览器,我很遗憾地说你需要自学C或C ++;)

Java应用程序具有C ++程序不具备的初始化开销。 在JITed时,它们不像C ++程序那样进行微优化。 此外,运行时开销很小(GC +间接调用开销)。 总的来说,这些可量化的差异并不是很多。 但…

众所周知,当Java应用程序首次启动时,它必须激活其磁通电容器才能将其环境带回1995年。这会在启动时引入一点延迟。 但是一旦结束,JVM的性能与从1995年在硬件上运行的类似C ++程序一样。