我正在尝试使用并行GC,基本上我试图将幸存者空间大小设置为先前运行时观察到的最大值,以避免幸存者空间溢出。在我的情况下,96mX2的幸存者应该没问题。为了避免jvm调整生存空间大小,我关闭了AdaptiveSizePolicy。
显然我错过了一些东西,因为我在应用程序上只有非常小的负载时会出现持续溢出,但仍然是一个奇怪的溢出,因为旧代空间似乎没有像溢出时那样增加。
这些是Java 1.7.0_51 jvm上的jvm args:
java -D [Standalone] -server -XX:+ UseCompressedOops -Xms3328m -Xmx3328m -Xmn1152m -XX:SurvivorRatio = 10 -XX:PermSize = 132m -XX:MaxPermSize = 132m -XX:+ UseParallelOldGC -XX:-UseAdaptiveSizePolicy -XX:+ PrintGCDetails -XX:+ PrintGCDateStamps -XX: + PrintAdaptiveSizePolicy -Xloggc:/usr/local/java/jboss/standalone/log/gc.log
这些是垃圾收集日志
2014-02-10T09:56:26.104 + 0200:39544.174: [GCAdaptiveSizePolicy :: compute_survivor_space_size_and_thresh: 幸存者:100636800晋升:10963760溢出:真实[PSYoungGen: 1081318K-> 98278K(1081344K)] 1869646K-> 897313K(3309568K),0.1578000 secs] [时间:用户= 0.57 sys = 0.03,实际= 0.16秒]
2014-02-10T10:02:24.729 + 0200:39902.799: [GCAdaptiveSizePolicy :: compute_survivor_space_size_and_thresh: 幸存:100648968晋升:19202536溢出:真实 [PSYoungGen: 1081318K-> 98290K(1081344K)] 1880353K-> 916077K(3309568K),0.1893170 secs] [时间:用户= 0.64 sys = 0.09,真实= 0.19秒]
这里旧的堆占用率增加了19米而不是96米(幸存者空间的大小)。其他日志也是如此。
2014-02-10T10:05:17.796 + 0200:40075.866: [GCAdaptiveSizePolicy :: compute_survivor_space_size_and_thresh: 幸存者:100623664晋升:1384448溢出:假[PSYoungGen: 1081330K-> 98265K(1081344K)] 1899117K-> 917405K(3309568K),0.1350010 secs] [时间:用户= 0.51 sys = 0.01,实际= 0.13秒]
2014-02-10T10:07:56.135 + 0200:40234.204: [GCAdaptiveSizePolicy :: compute_survivor_space_size_and_thresh: 幸存者:100650360晋升:19069104溢出:真实[PSYoungGen: 1081305K-> 98291K(1081344K)] 1900445K-> 936053K(3309568K),0.1847340 secs] [时间:用户= 0.64 sys = 0.08,真实= 0.18秒]
2014-02-10T10:08:26.613 + 0200:40264.682: [GCAdaptiveSizePolicy :: compute_survivor_space_size_and_thresh: 幸存者:100658976晋升:12245304溢出:真实[PSYoungGen: 1081331K-> 98299K(1081344K)] 1919093K-> 948020K(3309568K),0.1578130 secs] [时间:用户= 0.57 sys = 0.04,真实= 0.16秒]
所以问题是:我缺少什么?为什么这么多物体似乎存活下来?启用AdaptiveSizePolicy后,在相同负载下的生存率确实很低。
答案 0 :(得分:1)
经过一些实验后,我想我找到了答案。
首先,并行GC溢出到老一代只有幸存者空间之上,而不是我在问题中错误陈述的整个幸存者空间。
其次,当禁用AdaptiveSizePolicy时,tenuring threshold默认为2或更大,大于1的值(当几乎没有溢出时,AdaptiveSizePolicy在99%的情况下计算的值)。因此,在每个次要集合上,GC都会尝试将生存在第一个幸存者空间中的东西复制到第二个幸存者空间,但这里没有足够的空间(还有来自伊甸园的生物对象需要适应),所以它溢出到老一代。 /强>
将初始暂停阈值和最大暂停阈值设置为1可防止持续溢出,同时保持幸存者空间足够大,因为我最初打算:
java -D [Standalone] -server -XX:+ UseCompressedOops -Xms3328m -Xmx3328m -Xmn1152m -XX:SurvivorRatio = 10 -XX:PermSize = 132m -XX:MaxPermSize = 132m -XX:+ UseParallelOldGC -XX:-UseAdaptiveSizePolicy - XX:InitialTenuringThreshold = 1 -XX:MaxTenuringThreshold = 1 - XX:+ PrintGCDetails -XX:+ PrintGCDateStamps -XX:+ PrintAdaptiveSizePolicy -Xloggc:/usr/local/java/jboss/standalone/log/gc.log
这是打开时AdaptiveSizePolicy打印的日志:
2014-02-12T20:31:28.967 + 0200:74464.855: [GCAdaptiveSizePolicy :: compute_survivor_space_size_and_thresh: 幸存:21423336提升:4189088溢出: 假强>
AdaptiveSizeStart:74464.928集合:250
avg_survived_padded_avg:35720128.000000 avg_promoted_padded_avg: 21338244.000000 avg_pretenured_padded_avg:0.000000 tenuring_thresh:1 target_size: 36175872PS ...
有趣的是,与老一代的恒定溢出相比,1的老化使应用性能大不相同,主要是收集时间较短,而且全GC频率较小。