提问者:小点点

在什么情况下,Java 性能会随着内存的增加而降低?


我们正在DEV环境中对 Java 1.6应用程序进行负载测试。JVM堆分配为2Gb,-Xms2048m-Xmx2048m。在负载测试下,应用程序运行流畅,从不使用超过1.25Gb的堆,垃圾回收机制完全正常。

在我们的UAT环境中,我们使用相同的参数运行负载测试,唯一的区别是JVM,它分配了4Gb,-Xms4096m -Xmx4096m,否则,硬件与DEV完全相同。但是在负载测试期间,性能是可怕的,应用程序几乎吃掉了整个堆,垃圾收集运行猖獗。

我们一遍又一遍地运行这些测试,消除了所有可能影响性能的症状,但结果是一样的。在什么情况下会这样?


共3个答案

匿名用户

生产环境和UAT环境中的应用程序有些不同。

从症状来看,不太可能是硬件、操作系统性能调整或JVM版本的差异。不言而喻,这不太可能是由于应用程序有更多的内存。

(你的应用程序可能会做一些奇怪的事情,比如根据最大堆大小调整某些数据结构的大小,从而导致计算错误,这不是不可想象的。但我想你应该意识到这种可能性,所以现在就忽略它吧。)

这可能与操作系统环境的差异有关;例如,操作系统或某个应用程序的不同版本、网络的差异、语言环境的差异等。但底线是,99%确定在UAT上运行时应用程序中有内存泄漏,而内存泄漏就是占用堆内存和GC过载的原因。

我的建议是将此视为存储泄漏问题,并使用标准工具/技术来跟踪问题的原因。在这个过程中,你很可能会弄清楚为什么这种情况只发生在你的UAT上。

匿名用户

罪魁祸首可能是垃圾回收,正常的“停止世界”类型的收集给我们带来了一些性能问题;服务器软件运行非常缓慢,但服务器的负载也很低。最终我们发现,有一个“停止世界”的垃圾收集器线程在特定情况下(产生大量垃圾的操作)一直保持整个软件的运行。

移动到并发垃圾收集缓解了启动参数-XX:UseParallelOldGC-XX:ParallelGCThreads=8的问题。我们在测试和生产中只使用了“2gb”堆,但值得注意的是,GC所需的时间随着堆的增大而增加(即使您的软件从未实际使用过所有堆)。

您可能想从这里了解更多关于不同垃圾收集器选项和调优的信息:Java SE 6 HotSpot[tm]虚拟机垃圾收集调优。

此外,这个问题的答案可以提供一些帮助:Java非常大的堆大小。

匿名用户

值得分析这两台机器上的堆转储,并了解在这两种环境中是什么在不同地消耗堆。直方图会有帮助。