【问题标题】:Why CMS garbage collector does not utilize the whole CPU为什么 CMS 垃圾收集器不使用整个 CPU
【发布时间】:2020-11-16 09:13:13
【问题描述】:

在 Java Performance The Definitive guide 一书中,吞吐量垃圾收集器和 CMS 垃圾收集器的 CPU 利用率比较如下:

吞吐量收集器将(默认情况下)消耗 100% 的 CPU 在机器运行时可用,因此更准确 此测试期间 CPU 使用率的表示如图所示 5-2。大多数时候,只有应用程序线程在运行, 占用总 CPU 的 25%。当 GC 启动时,100% 的 CPU 消耗。因此,实际的 CPU 使用率类似于锯齿模式 在图中,即使测试期间的平均值报告为 直线虚线的值。

在并发收集器中效果不同,当有 与应用程序同时运行的后台线程 线程。在这种情况下,CPU 图表可能如图 5-3 所示。

应用程序线程使用总 CPU 的 25% 启动。 最终它为 CMS 后台线程创建了足够的垃圾 踢;该线程还消耗整个 CPU,导致 总计高达 50%。当 CMS 线程完成时,CPU 使用率下降到 25%, 等等。请注意,没有 100% 的 CPU 峰值时段,这是一个 一点点简化:会有很短的尖峰 在 CMS 新生代收集期间 CPU 使用率为 100%,但那些 足够短,我们可以在讨论中忽略它们。

我知道吞吐量垃圾收集器在运行时会停止所有应用程序线程,而 CMS 垃圾收集器与其他应用程序线程同时运行,但我不明白为什么当吞吐量收集器启动时它会使用整个 CPU 周期并将 CPU 利用率增加到100% 但是当 CMS 收集器启动时,它会留下 50% 的 CPU 未使用?是否有任何东西阻止 CMS 收集器使用所有可用的 CPU 资源?

【问题讨论】:

    标签: java garbage-collection


    【解决方案1】:

    由于 CMS 收集器同时执行一些工作,因此它的设计目的是不使用所有可用的系统资源,而是更像一个后台任务。 G1 和 ZGC 更是如此。

    由于并行收集器是同步的,它旨在利用所有可用的系统资源尽快完成工作。

    【讨论】:

    • 谢谢你回答了我的问题,但我遇到了另一个问题:我们现在 CMS 的 CPU 利用率应该高于吞吐量,为什么在这种情况下 CMS 的整体 CPU 利用率不高?
    • @Tashkhisi 收集器采用的并发级别越高,它总体消耗的系统资源就越多。
    【解决方案2】:

    我喜欢这个虚构的图表与现实几乎没有联系;然后CMS 被弃用并在java-14 中删除,仅供参考。到目前为止,我也不是 GC 专家,但作为免责声明,我喜欢摆弄不同的代码实现(尤其是在Shenandoah 代码库中)。

    想一想:当您停止这个世界并把每个线程都集中起来执行GC 时,您的首要任务就是快速、非常快地完成。由于找出什么是垃圾并四处移动以清除区域是一项 CPU 绑定任务,因此您希望使用尽可能多的 CPU 和尽可能多的线程来执行该任务。所以CMS 和其他收集器在他们的STW 暂停中会将CPU 峰值提高到最大值,从而更快地完成工作。由于吞吐量收集器根本没有任何并发​​暂停,因此这些峰值可能更明显。相比之下,CMS 中的一些 阶段是concurrent,因此 CPU 利用率在图表上可能不太明显。

    有趣的是,某些垃圾收集器会故意使您的应用程序运行速度变慢。他们可以为您的“mutator”(您的应用程序)线程提供较低的优先级,并从 GC 实现本身提高这些线程的优先级。 Shenandoah 称之为“起搏”,当分配率太高而 GC 线程无法处理时,它就会这样做。

    但我要重复一遍,这是一个虚构的图表,到目前为止,对 CPU 利用率的真正理解和正确结论并非易事。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-07
      • 2022-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多