Tashkhisi
Tashkhisi

Reputation: 2262

Why CMS garbage collector does not utilize the whole CPU

In the book Java Performance The Definitive guide There is a comparison between CPU utilization of throughput garbage Collector and CMS garbage collector as bellow:

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.

enter image description here

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.

enter image description here

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.

I know when Throughput garbage collector is running it stops all application thread while CMS garbage collector run concurrently with other application threads but I can't understand why when throughput collector kicks in it can uses the whole CPU cycles and increases CPU utilization to 100% but when CMS collector kicks in it lefts 50% of CPU unutilized? Is there anything that prevent CMS collector to use all CPU resources that are available?

Upvotes: 1

Views: 199

Answers (2)

Eugene
Eugene

Reputation: 120878

I love this made-up graphs with little to no connection to reality; then CMS is deprecated and removed in java-14, just FYI. I am also by far not a GC expert, but I love to fiddle around different code implementations (especially in Shenandoah codebase), as a disclaimer.

Think about it: when you stop the world and bring every thread to a hault to do the GC, your number one priority is to do that fast, very fast. Since finding out what is garbage and moving things around to clear regions is a CPU bound task, you want to involve as many CPUs as possible and as many threads reasonable, to perform that. So CMS as well as the other collector, in their STW pauses will spike the CPU to max, so that work gets done faster. Since throughput collector does not have any concurrent pauses at all, these spikes might be more visible. In contrast, some phases in CMS are concurrent, so CPU utilization might be not such much visible on graphs.

It is also interesting to notice that certain garbage collectors can make your application run slower, on purpose. They can give a lower priority to your "mutator" (your application) threads and raise the ones from the GC implementation itself. Shenandoah calls this "pacing" and it does that when the allocation rate is just too high for GC threads to deal with.

But I will just repeat, that is a made-up graph and true understanding and proper conclusions on CPU utilization are by far, not trivial.

Upvotes: 0

user3453226
user3453226

Reputation:

Since the CMS collector performs some work concurrently, it is designed to not use all the available system resources and instead behave more like a background task. The same applies in greater degree to G1 and ZGC.

Since the parallel collector is synchronous, it is designed to use all the available system resources to complete work as soon as possible.

Upvotes: 1

Related Questions