Java虚拟机与.NET公共语言运行时的性能基准测试

37

您是否曾经为了性能问题而需要辩解使用.NET而不是基于Java的选择?

对于一个典型的高交易量处理系统,该系统可以执行以下操作:

  • 并发数据库事务
  • 数学计算
  • 与其他Web服务的交互(SOAP / XML,XML-RPC)

我的方法是在Java虚拟机和.NET CLR中编写基准测试代码,对上述操作在各种负载水平下进行基准测试并进行比较。

除了语言和平台偏好之外,我想知道您如何进行一项决定性的性能比较Java VM和.NET CLR之间有没有任何全面且受人尊重的基准测试存在?

有没有任何全面且受人尊重的基准测试存在?


再次强调一下,我想知道您在进行两个平台之间的性能比较时会采取什么方法——即代码复杂性/可读性、库支持等不是问题——性能是您评估的唯一标准。 - bunn_online
7个回答

35

我没有JVM和CLR效率的确切数字,但差异如果有的话可能很小。

然而,从语言方面来看,C#拥有比Java更多的低级结构,这将允许进行更多的优化。

这些结构包括:

  • 用户定义的值类型。快速分配,没有内存开销(如果我没记错,CLR和JVM中每个引用类型的内存开销都为12字节)。适用于让自己自然地表示为值的事物,例如向量和矩阵。因此,它们非常适合进行数学运算。结合使用refout,可以避免对这些大型值类型进行过多的复制。

  • 不安全的代码块,允许更接近底层的优化。例如,虽然CLR和JVM可以在某些情况下避免数组边界检查,但在很多情况下,它们不能,每次访问数组都需要检查索引是否仍在数组的范围内。在这里使用不安全的代码可以直接使用指针访问数组的内存并绕过任何边界检查。这可能会带来显着的性能提升。在非常底层的方面,还有stackalloc,它允许直接在堆栈上分配数组,而普通数组是在堆上分配的,这会更慢,但也更方便。我个人不知道stackalloc的任何实际应用。

  • 真正的泛型,不像Java的类型擦除泛型那样需要无谓的转换和装箱拆箱。但如果这是您的Java程序中的问题,则可以通过一些额外的工作轻松解决(例如从一个ArrayList<Integer>切换到在内部使用int[]缓冲区的自定义类型)。

这一切似乎偏向于C#,我认为C#具有更好的低级语言结构,可以帮助提高性能。然而,我怀疑这些差异是否真的很重要(而且如果您只是进行数据库访问,则使用指针对您毫无裨益,Java可能会更快),如果选择在其他方面阻碍了您(例如跨平台),那么就要考虑正确性和符合您要求的平台,而不是微小的性能差异。


2
@JulianR:感谢你客观的看法。我同意,C#拥有更好的低级构造(以及其他改进),但这可能是因为它有机会从Java的怪癖(错误?)中学习到了东西。 - bunn_online
3
如果有区别的话,可能会很小。哇,这些差异可能会非常大。例如,在.NET上,通用哈希表比JVM快17倍。http://fsharpnews.blogspot.co.uk/2010/05/java-vs-f.html - J D
2
我认为这是客观上更优越的。我同意C#通常更优秀,但Java在垃圾回收方面有一个巨大的优势。通过值类型和具体化泛型,.NET让你更容易地完全避开GC,但当这不可能时,JVM往往从一个显著更高度优化的GC实现中获得优势。事实上,JVM被用来开创新的GC算法... - J D
3
FFI(例如PInvoke)似乎是性能差距非常大的另一个领域。我听说在这里,Java比C#/F#慢10倍。 - J D
@JonHarrop - 嗯,我提到了Java的泛型系统来解决这个问题。虽然有些不方便,但你完全可以将Java泛型哈希映射的源代码复制一份,然后使用搜索/替换功能将'T'替换为'int',以避免那些装箱操作 :) 但是,确实,一个Dictionary<int, int>比通用的Java等效物要快得多。 - JulianR
显示剩余7条评论

3
Java虚拟机和.NET CLR之间的决定性性能比较是一场空想。由于开发复杂系统总是需要做出妥协,因此您始终可以进行使其中一个看起来比另一个更优秀的性能测试。如果将基准测试限制在运行时速度和内存方面,您可能会找到像这样的文章:http://www.codeproject.com/KB/dotnet/RuntimePerformance.aspx,但这并不意味着辩论结束。

2
除了语言和平台偏好之外,我对听取您如何进行Java VM和.Net CLR之间的性能比较感兴趣?
我会编写一套基准测试,旨在让您比较两个VM及其标准库的各种不同特征。我的专业领域是技术计算,因此我建议以下内容:
- 寄存器整数运算,例如斐波那契数列。 - 寄存器浮点运算,例如曼德博集合。 - 数组迭代,例如FFT。 - 分配,例如纯函数红黑树。 - 具有int或float键和值的哈希表。 - 具有字符串键和值的哈希表。 - 字符串。 - 正则表达式。 - 文件IO。
也许您可以为数据库和Web服务想出类似的东西。
不要忘记,位于CLR之上的语言具有非常不同的属性。例如,F#语言中的“inline”让您自动执行优化,可以比C#获得巨大的性能增益。相反,在C#中使用“goto”可以比在F#中更有效地完成某些操作,并且结构体的优化在C#中比F#(我最近查看)更有效。
有没有任何全面且受人尊敬的基准存在?
没有,但是有很多零散的基准,它们关注的是离群值,因为它们更有趣。例如,这篇博客文章 解释了为什么在 .NET 上使用 F# 编写的简单通用哈希表基准测试可以比在 JVM 上使用 Java 快 17 倍。在这种情况下,原因是值类型和具体化泛型使得在 .NET 上编写更高效的通用哈希表实现成为可能,而在 JVM 上则不行。

1

是的,有一个基准测试游戏,它非常全面,可以让你比较很多不同的东西。

http://shootout.alioth.debian.org/

唯一的区别是它使用mono而不是Visual Studio,但是两者之间的性能差异现在非常小。

一般来说,Java通常稍微快一些(取决于你正在做什么),但占用的内存却要大得多,并且它们的源代码大小大致相同。


就复杂性而言,我们所做的事情在两个平台上都是相当标准和得到良好支持的。然而,我们希望确定我们将选择能够为我们提供最佳性能和可扩展性的平台。 - bunn_online
1
唯一的问题是它使用Mono而不是Visual Studio,但两者之间的性能差异现在非常小。这取决于具体情况。例如,比较在Mono和.NET上运行n-body测试所需的时间。这个差异并不小。 - konrad.kruczynski
唯一的区别是它使用的是Mono而不是Visual Studio,但是两者之间的性能差异现在非常小。在这个数字计算基准测试中,.NET比Mono快50%。http://flyingfrogblog.blogspot.co.uk/2009/01/mono-22.html - J D

1

提醒一下,未经微软批准,您不得使用.NET框架代码进行任何形式的基准测试。

如果您确实想要发布一些东西,我想让您知道。

据我记忆,微软曾经做过一些书店、宠物店之类的事情,这是Java先做的,以展示他们的软件如何在相同的任务上更有效地工作。我在努力回想它的名字。

.NET宠物店


7
忽略“宠物店基准测试”。微软拿了一个Java教程并制作了一个优化的.NET版本。猜猜哪个版本更易于阅读,哪个更快。在我看来,这证明了.NET实际上是更慢的,否则他们会选择一场公平的竞争。(注意:是过去时而不是现在时)。 - MSalters
对于那些对“宠物店基准测试”感兴趣的人,请访问:http://www.theregister.co.uk/2001/11/12/pet_vs_pet_ms_opens/ - bunn_online
@MSalters 我还没有看到过在我的客户端上,Java应用程序比.Net表现更好的情况。除非Java有类似于Linq和Linq to SQL的表达能力,否则我认为他们在可读性方面并不处于优势地位。 - Spence
5
@Spence,你确定吗?现在已经不是90年代了。我曾在非线性数学环境中正式对比过Java、C ++和FORTRAN,Java和C ++在多项测试中相差不到2%。FORTRAN始终比它们快20%。我的观点是Java不慢。 - Jé Queue
我确信针对基于网站的系统,Java与.Net的基准测试中,由于操作系统HTTP.sys驱动在IIS中提供了卓越的性能增益,因此后者更快。我并不是要一概而论地认为C#是世界上最好的语言,但在这个特定的基准测试中,Java表现得很差。 - Spence
显示剩余2条评论

1
基准测试...你可以通过适合你需求的测试来证明几乎所有事情。
除了查克·诺里斯。如果他愿意,查克·诺里斯比X更慢或更快。
另一点。假设你得出结论,Java更快。那是否意味着两年后它仍然会更快?
如果Java快5%,而.NET更易于使用10%,你会选择哪个?
有许多因素,性能只是其中之一。如果差异很小(我认为是这样),它可能不是最重要的因素。
除非你正在构建非常关键的性能问题。

1
为了这个问题,性能是我想要评估的标准。我知道在选择语言/平台时有许多其他标准(代码复杂性/可读性、技能可用性等等),但我的问题是确定其他人如何在两个平台之间进行性能评估的方法。 - bunn_online
“你几乎可以用适合你需求的测试来证明任何事情。”不,你不能。我认为你的意思是你可以试图欺骗人们,但OP感兴趣的是收集有用的信息,这完全可行。 - J D

1

我也一直在想哪种方法会提供更好的性能。但是我不知道如何进行基准测试。

所以这是一个好问题 - 希望我们都能在这里得到一些指导。

我猜测这种基准测试需要采用“折扣”基准测试方法(由一个开发人员轻松设置和运行)?

如果有人拥有这种信息,那就太好了。我经常被要求在短时间内独自评估技术。

干得好bunn_online!


@ForerMedia 感谢您将讨论重新引回正轨。我们经常基于偏见(供应商/平台忠诚度等)和不客观的观点做出决策。我提出这个问题的目的是想看看其他人会如何处理。他们会使用什么方法、工具和覆盖范围等。 - bunn_online

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接