1

我遇到了 GC 花费大量时间但不确定可能是什么原因的情况。这是jstat -gc命令的输出

S0C     S1C     S0U     S1U EC        EU       OC        OU        PC       PU       YGC  YGCT      FGC FGCT      GCT
77440.0 73088.0 22896.4 0.0 1946624.0 222690.4 4194304.0 3638965.1 262144.0 216641.1 1093 11258.452 3   10031.493 21289.944

Full GC 运行了 3 次,完成时间为 100031 秒,即平均 55 分钟,YGC 平均需要 15 秒。

这是应用服务器的启动脚本:

-Xms6144m -Xmx6144m -XX:MaxPermSize=256m -Djava.security.policy=/bea/wlserver_10.3/server/lib/weblogic.policy -Dweblogic.ProductionModeEnabled=true -da -Dplatform.home=/bea/wlserver_10.3 -Dwls.home=/bea/wlserver_10.3/server -Dweblogic.home=/bea/wlserver_10.3/server -Dweblogic.management.discover=true -Dwlw.iterativeDev=false -Dwlw.testConsole=false -Dwlw.logErrorsToConsole=false -Dweblogic.ext.dirs=/bea/patch_wls1036/profiles/default/sysext_manifest_classpath -Djava.awt.headless=true -Djava.net.preferIPv4Stack=true -Duser.timezone=GMT -Dfile.encoding=UTF-8 -Duser.language=en -Duser.country=US -Dweblogic.wsee.wstx.wsat.deployed=false -XX:+DisableExplicitGC

Operating system is Sun OS 5.1
Java version 1.6.0_41

GC算法默认,即Young Gen设置为PS Scavenge,Old GC设置为PS MarkSweep

这么高的数字可能是什么原因,请告诉我。

4

3 回答 3

1

哇,是的,那是一些旧硬件。之所以这么慢,是因为 6Gb 堆对于默认串行收集器来说是一个巨大的堆——它是为不大于几百兆字节的堆设计的。

我会尝试使用其他垃圾收集器,直到找到一个暂停时间最少的垃圾收集器。在一个多千兆字节的堆上,如果这样一台旧机器确实有这么多内存,我会查看 -XX:+UseConcMarkSweepGC,如果只有一个 CPU 核心,那么另外还有 -XX:+CMSIncrementalMode。

如果您实际上有多个 CPU,我会查看 -XX:+UseParallelGC 和 -XX:+UseParallelOldGC。作为最后的手段,您可以查看Java 6 中的实验性G1 收集器-XX:+UseG1GC。

更新:你可以重新运行你的jstatwith-XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:-UseAdaptiveSizePolicy吗?

于 2013-11-14T13:50:11.180 回答
0

运行 VMStat 5 小时得到以下结果,我提供了部分输出:
swap free re mf pi po

40336468 4025208 383 5473 465 59
40336132 4025732 383 5477 465 59
40336020 4025732 383 5478 465 59
40335940 4025752 383 5479 465 59
40335860 4025776 383 5479 465 59
40335776 4025796 383 5480 465 59
40335696 4025816 383 5481 465 59
40335584 4025816 383 5482 464 59
40335504 4025836 383 5483 464 59
40335420 4025856 383 5484 464 59

于 2013-11-15T02:10:24.263 回答
0

看看你原来的 jstat 这些是我注意到的东西......

您在老一代中获得了完整的 GC,因为它被高度利用(3.5G 使用了 4G 可用)。

默认情况下,VM 在年轻代(Eden+Survivor)和老年代之间以大约 45/55 的比例拆分堆,但也应用了一些启发式方法。

Eden 容量为 1.9G,但利用率仅为 217M (~12%)。每个生存空间约75M,利用率约22M。老一代是4G,利用率高达3.5G。

在我看来,这有点像从年轻到老的过度激进的提升,混合了大小不一的年轻人和老年人以满足您的需求。对于您的需求,Young 似乎有些过大。然而,修复过度激进的晋升确实需要杨的空间。

一、调整Young:

-XX:NewRatio=5

这会将 Young (Eden+Survivor) 设置为总堆的1/6(是的,1/6 而不是 1/5)。在你的情况下,~980M 而不是 1.9G。这会将另一个 1G 推送到老年代堆。

其次,让我们尽量避免过快提升中等生命周期的对象。尝试:

-XX:InitialTenuringThreshold=16 -XX:MaxTenuringThreshold=32

但是为了让幸存者在晋升前停留更长时间,我们需要增加幸存者的空间(从伊甸园中雕刻一点):

-XX:SurvivorRatio=6

将此与我的第一个答案中的选项以及您的选项相结合,您总共可以获得:

-Xms6144m -Xmx6144m -XX:MaxPermSize=256m
-XX:NewRatio=5
-XX:SurvivorRatio=6 -XX:InitialTenuringThreshold=16 -XX:MaxTenuringThreshold=32
-XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:-UseAdaptiveSizePolicy

您可能要添加:

-XX:+PrintTenuringDistribution

在研究这些选项时。

于 2013-11-15T04:23:18.910 回答