Java应用程序因堆而慢

时间:2013-08-16 14:53:19

标签: java performance jvm tomcat6

我们在高峰时间有严重的应用程序问题应用程序变得非常慢,当我检查AppDynamics矩阵时,我的堆内存已满并且GC每分钟都会启动,这使得它非常慢。这是我的java(tomcat)

的配置
OS version is Redhat 5 Linux

java version "1.6.0_05" 64Bit

Java选项是-Djava.awt.headless=true -Xmx2048m -XX:MaxPermSize=256m -XX:+HeapDumpOnOutOfMemoryError -XX:+UseConcMarkSweepGC -XX:+DisableExplicitGC

主要GC收集时间每分钟花费(毫秒)

enter image description here

以MB为单位的CMS Old Gen用法

enter image description here

标准伊甸园空间(MB)

enter image description here

有什么建议为什么标准的伊甸园空间和老一代打硬线?

更新

以下是堆使用率和主要GC收集的最后12小时图片(绿点),GC在3:00AM to 7:00AM之间非常高但是当我重新启动应用程序7:30AM时一切都很好并且应用程序响应时间很快,为什么重新启动固定一切?

enter image description here

万岁! 4GB堆解决了问题

4GB(零主要GC)后每分钟主要GC收集时间(ms)

enter image description here

4GB堆后的MB老化用法(MB)

enter image description here

4GB堆后的MB Eden空间

enter image description here

3 个答案:

答案 0 :(得分:3)

每分钟一个主要的GC一点都不麻烦。通常需要大约半秒钟,因此这是整体CPU使用率的1/120。重载应用程序负载导致更多内存分配也很自然。显然你正在分配一些存在一段时间的对象(可能是缓存)。

我的结论:演示的GC行为并不能证明应用程序的内存分配有问题。

更新

我仔细查看了你的图表(遗憾的是它们很难阅读)。你每分钟没有一个GC;你每分钟有60 的主要GC,这意味着它一直在发生。 看起来像是主要的麻烦;实际上在这些情况下,由于“GC时间百分比阈值超过”,您通常会获得OOME。请注意,您使用的CMS收集器实际上比默认收集器慢;它的优点只在于它不会“遏制世界”。它可能不是你的最佳选择。但是你确实要么有内存泄漏,要么是程序设计中的一般问题。

答案 1 :(得分:2)

当JVM达到堆最大大小时,会更频繁地调用GC以防止OOM异常。在这种情况下不应该执行正常的程序。分配新对象且JVM无法获得足够的可用空间时,将调用GC。这可能会推迟对象分配过程,从而降低整体性能。在这种情况下,垃圾收集不会同时发生,并且您不会从CMS收集器中受益。尝试使用CMSInitiatingOccupancyFraction,其默认值约为90%。将此参数设置为较低值,将在应用程序达到堆最大值之前强制进行垃圾回收。因此,GC将与不与其发生冲突的应用程序并行工作。看一下文章Starting a Concurrent Collection Cycle

答案 2 :(得分:1)

您是否一直在等待GC处理删除未使用的引用?您的应用程序中是否有一些地方您知道从那时起不再使用重量级对象的引用,但它不是手动为空的?也许在正确的位置手动设置如此重的对象为空可能会阻止它们生长,直到它们到达堆的末端....