【问题标题】:When to choose SerialGC, ParallelGC over CMS, G1 in Java?何时选择 SerialGC、ParallelGC 而不是 CMS、Java 中的 G1?
【发布时间】:2019-02-10 11:30:22
【问题描述】:

在 Java 9 中,G1 GC 是默认的垃圾收集器。 到目前为止,我听说过 G1GC 上的 some people preferring CMS garbage collector,因为它似乎不稳定并且有一些令人讨厌的错误。

ParallelGC 发生了什么(这些天没有嗡嗡声)? 有没有我们更喜欢 ParallelGC 而不是 CMS/G1 的用例?

另外,SerialGC 在任何情况下都无法执行所有这些并行收集器?

【问题讨论】:

  • AFAIK SerialGC 可以用于如果应用程序消耗尽可能少的本机内存至关重要,因为它与Shenandoah GC 一起具有最小的开销之一。
  • G1GC 在当前的 Java 版本中是稳定的。您正在查看旧版本的 ElasticSearch 文档中的建议。但是你不应该使用 Java 9,因为它是 EOL。而且我猜这意味着其他版本中针对 G1GC 的任何新错误修复都不会移植到 Java 9。

标签: java garbage-collection jvm


【解决方案1】:

串行收集器

主要针对单cpu机器。

算法:

它使用单个线程来处理堆,并在任何 gc 期间执行 stop-the-world 暂停。只是把它当作玩具。

这是客户端类机器的默认设置(Windows 或单 CPU 机器上的 32 位 jvm)


并行收集器

算法:

它使用多个 gc 线程来处理堆,并在任何 gc 期间执行 stop-the-world 暂停。

8,这是服务器级机器(多 CPU 类 unix 机器或任何 64 位 jvm)的默认设置。


CMS 收集器

它旨在消除与并行和串行收集器的完整 gc 相关的长时间暂停。

算法:

它使用1个或多个gc线程定期扫描老年代,并丢弃未使用的对象,暂停很短,但使用更多cpu时间。

警告:由于 Java 14,它已被删除


G1 收集器

它是低暂停/服务器风格的 gc,主要用于大堆(> 4Gb)。

算法:

  • 与 CMS 类似,它使用多个后台 gc 线程来扫描和清除堆。
  • 它将老年代分成几部分,它可以通过从一个部分复制到另一个部分来清理老年代。
    因此,产生碎片的可能性较小。

由于 Java 9,这是服务器级机器(多 CPU 类 unix 机器或任何 64 位 jvm)的默认设置。


为什么默认使用 G1?

主要原因是减少 gc 暂停时间,尽管整体吞吐量可能会降低。

【讨论】:

  • 好的。但是什么时候使用哪种算法呢?假设我的应用需要 2 个核心 cpu 机器和 1 GB 堆。我应该使用并行、CMS 还是 G1?
  • 我认为 CMS 和 G1 都可以正常工作。并行可能也足够好。如果您的应用程序是实时的(例如交易系统),并且需要非常低的暂停,那么使用 G1 或 CMS(对我来说 G1 是选择),否则您也可以使用并行收集器。对于像这样的小型应用程序,这并不重要。可能更重要的是启用带有轮换的 gc 日志,在出现问题时检查它,以及借助 Visualvm、内置命令 jmap、jcmd 等工具。然后根据需要切换收集器。如果您懒得查看详细信息,请使用 G1。
【解决方案2】:

您可以阅读文档Java Platform, Standard Edition HotSpot Virtual Machine Garbage Collection Tuning Guide-Java9

  • 串行收集器

    它最适合单处理器机器,因为它不能利用多处理器硬件,尽管它可以在多处理器上用于具有小数据集(最大约 100 MB)的应用程序。

  • 并行收集器

    并行收集器也称为吞吐量收集器,它是一种类似于串行收集器的分代收集器。串行收集器和并行收集器之间的主要区别在于并行收集器有多个线程用于加速垃圾收集。 并行收集器适用于在多处理器或多线程硬件上运行的中型到大型数据集的应用程序。 如果您不关心暂停时间并且更喜欢吞吐量,那么这个收集器会是最好的。

  • 大多数并发收集器 (CMS)

此收集器在 Java9 中已弃用。

此收集器适用于喜欢较短的垃圾收集暂停并且能够负担与垃圾收集共享处理器资源的应用程序。

  • G1 垃圾收集器

    这种服务器式收集器适用于具有大量内存的多处理器机器。它以高概率满足垃圾收集暂停时间目标,同时实现高吞吐量。

总结:

  • 如果应用程序的数据集较小(最大约 100 MB),则使用选项 -XX:+UseSerialGC 选择串行收集器。

  • 如果应用程序将在单处理器上运行并且没有暂停时间要求,则使用选项 -XX:+UseSerialGC 选择串行收集器。

  • 如果 (a) 峰值应用程序性能是第一优先级,并且 (b) 没有暂停时间要求或可接受一秒或更长的暂停,则让 VM 选择收集器或选择并行收集器使用 -XX:+UseParallelGC。

  • 如果响应时间比整体吞吐量更重要,并且垃圾收集暂停必须保持在大约一秒以内,则选择带有 -XX:+UseG1GC 或 -XX:+UseConcMarkSweepGC 的并发收集器。

问答:

  1. 我听说有些人更喜欢 CMS 垃圾收集器而不是 G1GC,因为它似乎不稳定并且存在一些令人讨厌的错误。

G1 收集器对于大多数应用程序来说足够稳定。我在许多应用程序中都使用了 G1 收集器,它们都运行良好。如果能把java9升级到Java11,效果会更好,bug也更少。

  1. 是否存在我们希望 ParallelGC 优于 CMS/G1 的用例?

是的。一些需要更多吞吐量并且不关心使用并行收集器的暂停时间的应用程序会更好。例如,批处理任务、离线作业、计算任务。

  1. 另外,SerialGC 在任何情况下都无法执行所有这些并行收集器?

如果你在嵌入式系统上运行JVM,或者一些有一个或两个CPU的系统,Serial GC会更好。

最后,G1 VS CMS: 大多数情况下,G1 可以替代 CMS。在这种情况下,你最好使用 G1:

  1. 你有一个大堆,比如 16G。暂停时间和堆大小呈正相关。相反,G1是增量收集器。
  2. 您有严格的暂停时间要求,并希望暂停时间更可控。比如,你想要暂停时间

【讨论】:

    【解决方案3】:

    使用序列号:
    - 只有 1 个 CPU 可用,没有暂停要求 - 单个机器上存在小型 JVM(超过 CPU 数量) - 小型实时数据集(小于 100MB)

    使用并行:
    - 非交互式批处理应用程序,其中应用程序性能比低暂停时间更重要

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-24
      • 2018-01-31
      • 1970-01-01
      • 2018-04-13
      • 2010-12-19
      • 1970-01-01
      相关资源
      最近更新 更多