【问题标题】:using Concurrent Mark Sweep GC Collector?使用并发标记扫描 GC 收集器?
【发布时间】:2014-08-26 21:57:18
【问题描述】:

这个问题是基于我对link 的 Java 垃圾收集器部分的理解 看起来 jvm 默认情况下在 Windows 7 上使用“Parallel GC”,因为我确认了它 -XX:+PrintCommandLineFlags -version。这篇文章还说

并行垃圾收集器使用多个线程来执行 年轻代垃圾回收。这个收集器应该在很多时候使用 工作需要完成,可以接受长时间的停顿

我不确定 Parallel GC 使用哪个收集器来收集永久空间?

我也想不出可以接受长时间停顿的应用程序(会导致响应速度降低)。任何人都希望减少 GC 的停顿并让应用尽可能地响应。

然后我读了Concurrent Mark Sweep (CMS) Collector,它收集了终身代

CMS 说it require low pause times and can share resources with the garbage collection

我的问题不应该是最 的 Web 应用程序使用 Concurrent Mark Sweep (CMS) Collector 因为它的响应能力。? 我相信还必须有一些其他因素才能使 决定,但是在通过这个链接给我之后,我觉得我应该将默认的 GC 类型更改为并发标记扫描 (CMS) 收集器。有什么想法/见解?

此外,我认为如果我们将 CMS 收集器和并行收集器一起使用,其中 CMS 用于老年代和并行 fpr,应用程序可能是最好的 年轻一代

【问题讨论】:

    标签: java garbage-collection


    【解决方案1】:

    我不确定 Parallel GC 使用哪个收集器来收集永久空间?

    离开this 页面,如果您使用并行 GC,则并行清除收集器用于年轻代,并行标记/清除收集器用于老一代(也称为终身代)。所以我猜答案是“Parallel GC 用于 Parallel GC 的永久空间收集”。有点循环的说法,但我认为这是有道理的。

    我也想不出可以接受长时间停顿的应用程序(会导致响应速度降低)。任何人都希望减少 GC 的停顿并让应用尽可能地响应。

    “长时间停顿”是相对的,是否可以接受取决于应用程序的类型及其用途。需要快速用户交互的应用程序,例如游戏,可能需要较短的暂停时间,而长时间运行的应用程序几乎没有用户交互(夜间批处理作业、可以运行几天的处理作业,可能是长时间运行的服务器时间段等),或者不需要快速用户交互(文字处理器?但是谁用Java编写文字处理器?)不会有几乎那么严格的暂停要求,所以暂停将是对那些没问题。此外,暂停不是唯一需要考虑的 GC 因素,因此即使暂停是可以的,也有其他原因会选择暂停时间更长的 GC。我会在下面进一步解释。

    我的问题是大多数 Web 应用程序不应该因为它的响应性而使用并发标记扫描 (CMS) 收集器吗?

    CMS 收集器有缺点。在你提到的文章中,有这样一行:

    通常并发低暂停收集器不会复制或压缩活动对象。在不移动活动对象的情况下完成垃圾收集。

    因此,没有堆压缩会导致堆碎片,这可能会损害性能。 This 帖子指出了另一个缺点(我不确定这篇帖子到底有多可靠,但乍一看似乎还不错):

    CMS 收集器的一个更重要的缺点与它在老年代堆满时无法启动有关。一旦老年代满了,CMS 就太晚了,它必须回退到通常的 stop-the-world 策略(通过 GC 日志中的“并发模式失败”来宣布)。

    ...

    然而,CMS 的最大缺点与它不压缩老年代堆有关。因此,随着时间的推移,它存在堆碎片和严重操作退化的风险。

    ...

    很明显,通过这些设置,JVM 在负载测试条件下运行了将近 14 个小时(在生产环境和较低负载下,这个危险的良性时期可能会持续更长的时间)。然后突然有很长的 GC 暂停,实际上停止了 JVM 大约一半的剩余时间。不仅有超过 10 秒的老年代清理混乱的尝试,甚至新生代 GC 暂停也在秒范围内,因为收集器在尝试清理老年代时花费了大量时间来寻找空间。将对象从新代提升到老代。

    博文中有更多详细信息,您可能应该阅读它,因为这里的引文之外还有很多内容以及一些精彩的演示。但要指出的是,CMS 收集器并不是万能的收集器。它也有缺点,这可能会导致程序员选择不同的收集器。使用它作为默认值对于短期运行的应用程序可能是可以的,但对于长时间运行的应用程序,这种行为会非常糟糕......

    此外,我认为如果我们将 CMS 收集器和并行收集器一起使用,其中 CMS 用于老年代和并行 fpr 新生代,应用程序会是最好的

    当您将-XX:+UseConcMarkSweepGC 参数传递给您的VM 时,这实际上是默认模式。但如上所述,您可能需要真正花一些时间来考虑要使用的收集器。在不考虑您的用例的情况下选择收集器可能不是一个好主意。 (旁注:我以为我从 Oracle 看到了一些关于如何决定使用什么 GC 的文档,但我再也找不到它了......)

    此外,如果您有 Java 7u4 或更高版本,您可能需要考虑使用闪亮的新 G1 收集器。它应该是 CMS 收集器的替代品。

    【讨论】:

    【解决方案2】:

    我不确定哪个收集器用于永久空间收集 并行 GC?

    如果您不指定标志“-XX:+UseParallelOldGC”,jvm 将根据机器上可用的内核数、操作系统、32/64 位等选择单线程或多线程收集器。

    我的问题是大多数 Web 应用程序不应该使用 Concurrent Mark 扫描 (CMS) 收集器,因为它的响应能力。?

    CMS 收集器的问题在于它不执行旧代内存压缩,从而导致内存分配性能下降,并最终像 Parallel GC 一样停止世界 FULL GC。

    如果您的 Web 应用程序使用的小堆 (4-5GB) 不经常填充(每天 1-2 次)并且 1 秒/(旧一代 GB)的暂停是可以接受的,那么并行 GC 是不错的选择。

    如果您有更大的堆,则 CMS 是更好的选择,因为它不会在收集老年代时导致世界暂停时间过长。但是无论如何,您都应该安排一次 FULL 内存 gc,比如说每天在非高峰时间进行一次,以便进行内存压缩。

    此外,我认为如果我们使用 CMS Collector 和 CMS 用于老年代的并行收集器和 并行fpr年轻一代

    它们不能设置为一起使用:并行 GC 和 CMS。但是年轻代收集是并行的,并且与两个收集器一起停止了世界。

    【讨论】:

    • 您说“如果您有更大的堆,CMS 是更好的选择”。我认为如果我们有更大的堆,你说这个堆碎片的原因不是问题。那正确吗 ?但是如果我们有很大的堆,即使是并行 gc 也不会那么频繁。所以会有停顿,但不会那么频繁。对吧?
    • 是的,并行 gc 将不那么频繁,但会阻塞 jvm 太长时间。 cms 是更好的选择,因为在收集老年代时不会阻塞 jvm。
    猜你喜欢
    • 2017-07-11
    • 1970-01-01
    • 2016-07-30
    • 1970-01-01
    • 2011-09-16
    • 2013-06-16
    • 2018-10-10
    • 1970-01-01
    相关资源
    最近更新 更多