我们正在DEV环境中加载测试Java 1.6应用程序。 JVM堆分配为2Gb,-Xms2048m -Xmx2048m。在负载测试下,应用程序运行流畅,从不使用超过1.25Gb的堆,垃圾收集完全正常。
在我们的UAT环境中,我们使用相同的参数运行负载测试,唯一的区别是JVM,它分配了4Gb,-Xms4096m -Xmx4096m,否则,硬件与DEV完全相同。但是在负载测试期间,性能非常糟糕,应用程序几乎吞噬了整个堆,并且垃圾收集泛滥。
我们一遍又一遍地运行这些测试,消除了可能影响性能的所有可能症状,但结果是一样的。在什么情况下会出现这种情况?
答案 0 :(得分:5)
您的应用程序在Production和UAT环境中有一些不同。
从症状来看,(IMO)不太可能是硬件,操作系统性能调整或JVM版本的差异。不言而喻,这不太可能是由于应用程序具有更多内存。
(你的应用程序可能会做一些奇怪的事情并不是不可思议的......比如根据最大堆大小调整一些数据结构并使计算错误。但我认为你会意识到这种可能性,所以让我们忽略它现在。)
可能与 OS环境的差异有关;例如操作系统或某些应用程序的不同版本,网络的差异,区域设置的差异等等。但最重要的是,99%的确定在UAT上运行时应用程序中存在内存泄漏,而内存泄漏正在扼杀堆内存并使GC过载。
我的建议是将此视为存储泄漏问题,并使用标准工具/技术来追踪问题的原因。在此过程中,您很可能会弄清楚为什么这只会发生在您的UAT上。
答案 1 :(得分:1)
罪魁祸首可能是垃圾收集,正常的“停止世界”型收集导致我们一些性能问题;服务器软件运行速度很慢,但服务器的负载也很低。最终我们发现有一个“停止世界” - 垃圾收集器线程阻止整个软件在某些情况下运行(操作产生大量垃圾)。
迁移到并发垃圾回收缓解了启动参数-XX:+UseParallelOldGC -XX:ParallelGCThreads=8
的问题。我们在测试和生产中使用“仅”2gb堆,但同样值得注意的是GC占用的时间越长,堆积越大(即使您的软件实际上从未使用过所有的堆)。
您可能希望从此处了解有关不同垃圾收集器 - 选项和调优的更多信息:Java SE 6 HotSpot[tm] Virtual Machine Garbage Collection Tuning。
此外,此问题的答案可以提供一些帮助:Java very large heap sizes。
答案 2 :(得分:1)
分析这两台计算机上的堆转储并了解在这两种环境中以不同方式消耗堆的情况是值得的。直方图将有所帮助。