UseConcMarkSweepGC与UseParallelGC的区别

28

我目前遇到非常长的垃圾回收时间问题,请看以下情况。我的当前设置是使用 -Xms1g 和 -Xmx3g。我的应用程序正在使用 Java 1.4.2。我没有设置任何垃圾回收标志。看起来,3GB 的内存不足以处理我需要回收的大量对象。

问题:

我应该更改垃圾回收算法吗?我应该使用什么?使用 -XX:+UseParallelGC 或者 -XX:+UseConcMarkSweepGC 哪一个更好?还是我应该使用这种组合?

-XX:+UseParNewGC -XX:+UseConcMarkSweepGC

主要占用内存的是报告数据而不是缓存数据。此外,机器有16GB内存,我计划将堆增加到8GB。

这两个选项有什么区别,因为我仍然觉得很难理解。该机器有多个处理器。我可以承受高达5秒的影响,但30到70秒真的很困难。

感谢帮助。

  Line 151493: [14/Jan/2012:11:47:48] WARNING ( 8710): CORE3283: stderr: [GC 1632936K->1020739K(2050552K), 1.2462436 secs]
    Line 157710: [14/Jan/2012:11:53:38] WARNING ( 8710): CORE3283: stderr: [GC 1670531K->1058755K(2050552K), 1.1555375 secs]
    Line 163840: [14/Jan/2012:12:00:42] WARNING ( 8710): CORE3283: stderr: [GC 1708547K->1097282K(2050552K), 1.1503118 secs]
    Line 169811: [14/Jan/2012:12:08:02] WARNING ( 8710): CORE3283: stderr: [GC 1747074K->1133764K(2050552K), 1.1017273 secs]
    Line 175879: [14/Jan/2012:12:14:18] WARNING ( 8710): CORE3283: stderr: [GC 1783556K->1173103K(2050552K), 1.2060946 secs]
    Line 176606: [14/Jan/2012:12:15:42] WARNING ( 8710): CORE3283: stderr: [Full GC 1265571K->1124875K(2050552K), 25.0670316 secs]
    Line 184755: [14/Jan/2012:12:25:53] WARNING ( 8710): CORE3283: stderr: [GC 2007435K->1176457K(2784880K), 1.2483770 secs]
    Line 193087: [14/Jan/2012:12:37:09] WARNING ( 8710): CORE3283: stderr: [GC 2059017K->1224285K(2784880K), 1.4739291 secs]
    Line 201377: [14/Jan/2012:12:51:08] WARNING ( 8710): CORE3283: stderr: [Full GC 2106845K->1215242K(2784880K), 30.4016208 secs]


xaa:1: [11/Oct/2011:16:00:28] WARNING (17125): CORE3283: stderr: [Full GC 3114936K->2985477K(3114944K), 53.0468651 secs] --> garbage collection occurring too often as noticed in the time. garbage being collected is quite low and if you would notice is quite close the the heap size. during the 53 seconds, this is equivalent to a pause.
xaa:2087: [11/Oct/2011:16:01:35] WARNING (17125): CORE3283: stderr: [Full GC 3114943K->2991338K(3114944K), 58.3776291 secs]
xaa:3897: [11/Oct/2011:16:02:33] WARNING (17125): CORE3283: stderr: [Full GC 3114940K->2997077K(3114944K), 55.3197974 secs]
xaa:5597: [11/Oct/2011:16:03:00] WARNING (17125): CORE3283: stderr: [Full GC[Unloading class sun.reflect.GeneratedConstructorAccessor119]
xaa:7936: [11/Oct/2011:16:04:36] WARNING (17125): CORE3283: stderr: [Full GC 3114938K->3004947K(3114944K), 55.5269911 secs]
xaa:9070: [11/Oct/2011:16:05:53] WARNING (17125): CORE3283: stderr: [Full GC 3114937K->3012793K(3114944K), 70.6993328 secs]

1
这是一个链接,可能对您有所帮助:http://www.oracle.com/technetwork/java/gc-tuning-5-138395.html。收集器是针对1.5特定的,但并行和并发扫描的概念在1.4中可能是相同的。 - kosa
4个回答

7

由于您的GC暂停时间极长,改变GC算法可能不会有所帮助。

请注意,您仅进行完整收集是非常可疑的。也许您需要增加年轻代和/或幸存者空间的大小。

另请参阅:


是的,这只会在生成报告时发生。这些对象来自数据库,它们具有非常大的值。我想知道是否有任何方法可以解决这个问题。在第二种情况下,我认为堆大小确实不足,所以我们计划增加它;对于第一种情况,堆仍然可用。垃圾回收时间约为25到30秒。 - grassbl8d
抱歉,我没能在其中包含另一个垃圾回收器。现在已经为第一个场景包含了它。 - grassbl8d

4
你的堆太小了。暂停时间很长,因为它在绝望地重复扫描整个堆,寻找任何可回收的东西。
你需要执行以下1项或多项操作:
- 找到并修复内存泄漏 - 调整应用程序以使用更少的内存 - 配置JVM使用更大的堆
你是否由于某些原因与1.4.2版本捆绑?自那时起,GC实现已经得到改进,所以如果可能的话,请考虑升级。我意识到这可能是一项非常困难的任务,但无论如何都值得考虑。

实际上,这只会在用户开始生成大型报告时发生,我们确实无法控制。这些报告非常大。目前,我们所在的服务器是1.4.2版本,迁移过程已经在进行中,但现在我们需要尽力而为。 - grassbl8d
对于场景1,我仍然有可用堆空间,因为我的最大堆大小为3GB,但垃圾回收时间仍然太长。 - grassbl8d
如果生成大型报告是正常操作的一部分,那么您的堆大小太小了。但您需要进行一些适当的基准测试来进行调整,而该努力的输出结果将至少部分地变得冗余,如果您转移到java6或java7 jvm。如果可以避免重复工作,则不应执行两次相同的工作。 - Matt
对于场景1,您需要收集有关堆的形状的更多数据。您需要查看的标志包括PrintTenuringDistributionverbose:gc-Xloggc:gc.logPrintGCDetailsPrintGCTimeStamps。一旦您获得了这些信息,人们就可以建议合理的调整步骤,可能会立即产生效益。毕竟,年轻代收集超过1秒是巨大的。 - Matt
FWIW,默认收集器在1.4中是单线程串行收集器。只需添加-XX:+UseParallelGC,年轻代收集的停顿时间几乎肯定会大幅缩短。请注意,要改善老年代收集器,您必须切换到CMS,因为我记得1.4中没有paralleloldgc。因此,一个好的策略可能是使用更大的堆和吞吐量收集器。但是,更大的堆意味着当发生老年代收集时,它可能会非常长。还要记住,CMS需要比并行收集器更大的堆才能工作。 - Matt

1

步骤1:

  1. 确保为应用程序设置了足够的内存。
  2. 确保应用程序中没有内存泄漏。Eclipse Memory Analyzer Toolvisualvm 可以帮助您识别应用程序中的内存泄漏。

步骤2:

如果在步骤1中关于内存泄漏没有任何问题,请参考 Oracle 文档 页面 的“Java Garbage Collectors”部分中针对特定垃圾回收算法的使用情况和 gctuning 文章。

由于您已经决定配置更大的堆(>= 8 GB),因此 G1GC 应该适合您。请参考这个相关的 SE 问题,以微调关键参数:

Java 7 (JDK 7) 垃圾回收和 G1 文档


1
如果您的生存率很高,那么您的堆可能太大了。堆越大,JVM 就可以在没有 GC 的情况下运行更长时间,因此一旦它触发,需要移动的内容也就更多了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接