为什么 CMS 垃圾收集器不利用整个 CPU
Why CMS garbage collector does not utilize the whole CPU
在 Java Performance The Definitive guide 一书中CPU throughput garbage Collector 和 CMS garbage collector 的利用率比较如下:
The throughput collector will (by default) consume 100% of the CPU
available on the machine while it runs, so a more accurate
representation of the CPU usage during this test is shown in Figure
5-2. Most of the time, only the application thread is running,
consuming 25% of the total CPU. When GC kicks in, 100% of the CPU is
consumed. Hence, the actual CPU usage resembles the sawtooth pattern
in the graph, even though the average during the test is reported as
the value of the straight dashed line.
The effect is different in a concurrent collector, when there are
background thread(s) running concurrently with the application
threads. In that case, a graph of the CPU might look like Figure 5-3.
The application thread starts by using 25% of the total CPU.
Eventually it has created enough garbage for the CMS background thread
to kick in; that thread also consumes an entire CPU, bringing the
total up to 50%. When the CMS thread finishes, CPU usage drops to 25%,
and so on. Note that there are no 100% peak-CPU periods, which is a
little bit of a simplification: there will be very short spikes to
100% CPU usage during the CMS young generation collections, but those
are short enough that we can ignore them for this discussion.
我知道吞吐量垃圾收集器何时 运行 停止所有应用程序线程,而 CMS 垃圾收集器 运行 与其他应用程序线程并发,但我不明白为什么当吞吐量收集器启动时可以使用整个 CPU 周期并将 CPU 利用率提高到 100%,但是当 CMS 收集器启动时它会留下 50% 的 CPU 未使用?是否有任何东西阻止 CMS 收集器使用所有可用的 CPU 资源?
由于 CMS 收集器并发执行一些工作,它被设计为不使用所有可用的系统资源,而是更像是一个后台任务。 G1和ZGC更是如此。
由于并行收集器是同步的,它被设计为使用所有可用的系统资源尽快完成工作。
我喜欢这些虚构的图表,与现实几乎没有联系;然后 CMS
在 java-14
中被弃用并删除,仅供参考。到目前为止,我也不是 GC 专家,但我喜欢 fiddle 围绕不同的代码实现( 尤其是 Shenandoah
代码库中的 ),作为免责声明。
想一想:当您 停止 世界并使每个线程都全力以赴地完成 GC
时,您的首要任务是快速完成,非常快。由于找出什么是垃圾并将东西四处移动以清除区域是一项 CPU 绑定任务,因此您希望涉及尽可能多的 CPU 和尽可能多的合理线程来执行该任务。所以 CMS
和其他收集器一样,在他们的 STW
暂停中会将 CPU 增加到最大值,这样工作就可以更快地完成。由于吞吐量收集器根本没有任何并发暂停,因此这些峰值可能更加明显。相比之下,CMS
中的 一些 阶段是 concurrent
,因此 CPU 利用率在图表上可能不那么明显。
值得注意的是,某些垃圾收集器可能会故意使您的应用程序 运行 变慢。他们可以为您的“mutator”(您的应用程序)线程提供较低的优先级,并从 GC 实现本身提升这些线程。 Shenandoah
将此称为“调整”,当分配率对于 GC 线程来说太高而无法处理时它会执行此操作。
但我要重复一遍,这是一张虚构的图表,到目前为止,对 CPU 利用率的真正理解和正确结论并非微不足道。
在 Java Performance The Definitive guide 一书中CPU throughput garbage Collector 和 CMS garbage collector 的利用率比较如下:
The throughput collector will (by default) consume 100% of the CPU available on the machine while it runs, so a more accurate representation of the CPU usage during this test is shown in Figure 5-2. Most of the time, only the application thread is running, consuming 25% of the total CPU. When GC kicks in, 100% of the CPU is consumed. Hence, the actual CPU usage resembles the sawtooth pattern in the graph, even though the average during the test is reported as the value of the straight dashed line.
The effect is different in a concurrent collector, when there are background thread(s) running concurrently with the application threads. In that case, a graph of the CPU might look like Figure 5-3.
The application thread starts by using 25% of the total CPU. Eventually it has created enough garbage for the CMS background thread to kick in; that thread also consumes an entire CPU, bringing the total up to 50%. When the CMS thread finishes, CPU usage drops to 25%, and so on. Note that there are no 100% peak-CPU periods, which is a little bit of a simplification: there will be very short spikes to 100% CPU usage during the CMS young generation collections, but those are short enough that we can ignore them for this discussion.
我知道吞吐量垃圾收集器何时 运行 停止所有应用程序线程,而 CMS 垃圾收集器 运行 与其他应用程序线程并发,但我不明白为什么当吞吐量收集器启动时可以使用整个 CPU 周期并将 CPU 利用率提高到 100%,但是当 CMS 收集器启动时它会留下 50% 的 CPU 未使用?是否有任何东西阻止 CMS 收集器使用所有可用的 CPU 资源?
由于 CMS 收集器并发执行一些工作,它被设计为不使用所有可用的系统资源,而是更像是一个后台任务。 G1和ZGC更是如此。
由于并行收集器是同步的,它被设计为使用所有可用的系统资源尽快完成工作。
我喜欢这些虚构的图表,与现实几乎没有联系;然后 CMS
在 java-14
中被弃用并删除,仅供参考。到目前为止,我也不是 GC 专家,但我喜欢 fiddle 围绕不同的代码实现( 尤其是 Shenandoah
代码库中的 ),作为免责声明。
想一想:当您 停止 世界并使每个线程都全力以赴地完成 GC
时,您的首要任务是快速完成,非常快。由于找出什么是垃圾并将东西四处移动以清除区域是一项 CPU 绑定任务,因此您希望涉及尽可能多的 CPU 和尽可能多的合理线程来执行该任务。所以 CMS
和其他收集器一样,在他们的 STW
暂停中会将 CPU 增加到最大值,这样工作就可以更快地完成。由于吞吐量收集器根本没有任何并发暂停,因此这些峰值可能更加明显。相比之下,CMS
中的 一些 阶段是 concurrent
,因此 CPU 利用率在图表上可能不那么明显。
值得注意的是,某些垃圾收集器可能会故意使您的应用程序 运行 变慢。他们可以为您的“mutator”(您的应用程序)线程提供较低的优先级,并从 GC 实现本身提升这些线程。 Shenandoah
将此称为“调整”,当分配率对于 GC 线程来说太高而无法处理时它会执行此操作。
但我要重复一遍,这是一张虚构的图表,到目前为止,对 CPU 利用率的真正理解和正确结论并非微不足道。