"-XX:ParallelGCThreads=6" - Old GC Parallel Threads

This section demonstrates that the '-XX:ParallelGCThreads=6' option can be used to control the number of threads used in Old GC parallel phases.

In previous tutorials, we learned that multiple threads are used by the CMS collector for stop-the-world (application paused) phases in an Old GC process.

For example, we saw 2 threads was used in the "Initial Mark" phase. If you want to increase the number of threads used in those stop-the-world phases, you can specify a higher number in the "-XX:ParallelGCThreads=n" option.

The example below shows all log messages of a single Old GC performed by the CMS collector with 6 threads specified in stop-the-world phases.

herong> java -XX:+UseConcMarkSweepGC \
   -Xms90m -Xmx90m -XX:NewRatio=2 -XX:SurvivorRatio=1 \
   -XX:CMSInitiatingOccupancyFraction=20 \
   -XX:+UseCMSInitiatingOccupancyOnly \
   -XX:ParallelGCThreads=6 \
   -Xlog:gc*=trace \
   GarbageCollection2 > output.txt

herong> more output.txt

GC(4) Pause Initial Mark
GC(4) checkpointRootsInitialWork
GC(4) eden 0x00000000fa600000-0x00000000fa700010-0x0000...
GC(4) _eden_chunk_index=1, _eden_chunk_capacity=1281
GC(4) _eden_chunk_array[0]=0x00000000fa700010
GC(4) survivor 0x00000000fb000000-0x00000000fb900090-0x0000...
GC(4) _survivor_chunk_index=0, _survivor_chunk_capacity=5120
GC(4) oops_do_marking_prologue
GC(4) WorkerManager::add_workers() : created_workers: 6
GC(4) GC Thread: using 6 out of 6 workers
GC(4) Finished young gen initial mark scan work in 2th thread: 0.000 sec
GC(4) Finished young gen initial mark scan work in 5th thread: 0.000 sec
GC(4) Finished young gen initial mark scan work in 1th thread: 0.000 sec
GC(4) Finished young gen initial mark scan work in 0th thread: 0.000 sec
GC(4) Finished young gen initial mark scan work in 3th thread: 0.000 sec
GC(4) Finished remaining root initial mark scan work in 2th thread: 0.000 sec
GC(4) Finished remaining root initial mark scan work in 0th thread: 0.000 sec
GC(4) Finished remaining root initial mark scan work in 1th thread: 0.000 sec
GC(4) Finished young gen initial mark scan work in 4th thread: 0.000 sec
GC(4) Finished remaining root initial mark scan work in 3th thread: 0.000 sec
GC(4) Finished remaining root initial mark scan work in 5th thread: 0.000 sec
GC(4) Finished remaining root initial mark scan work in 4th thread: 0.000 sec
GC(4) WorkerManager::add_workers() : created_workers: 6
GC(4) GC Thread: using 6 out of 6 workers
GC(4) oops_do_marking_epilogue
GC(4) checkpointRootsInitialWork 0.268ms
GC(4) Pause Initial Mark 27M->27M(80M) 0.302ms
GC(4) User=0.00s Sys=0.00s Real=0.00s
   -- Initial Mark phase, Pause
   -- 6 threads used as specified by -XX:ParallelGCThreads=6

GC(4) Concurrent Mark
GC(4) CMS Thread: using 2 out of 2 workers
GC(4) Using 2 workers of 2 for marking
GC(4) Finished cms space scanning in 0th thread: 0.007 sec
GC(4) Finished cms space scanning in 1th thread: 0.007 sec
GC(4) Finished work stealing in 1th thread: 0.000 sec
GC(4) Finished work stealing in 0th thread: 0.000 sec
GC(4) Concurrent active time: 0.002ms
GC(4)  (CMS Concurrent Mark yielded 1 times)
GC(4) Concurrent Mark 7.556ms
GC(4) User=0.03s Sys=0.00s Real=0.02s
   -- Mark phase, Concurrent
   -- 2 threads used by default

GC(4) Concurrent Preclean
GC(4) Preclean SoftReferences 0.028ms
GC(4) Preclean WeakReferences 0.039ms
GC(4) Preclean FinalReferences 0.020ms
GC(4) Preclean PhantomReferences 0.024ms
GC(4) Concurrent Preclean 0.418ms
GC(4) User=0.00s Sys=0.00s Real=0.00s
   -- Preclean phase, Concurrent

GC(4) Concurrent Abortable Preclean
GC(4) Concurrent Abortable Preclean 36.072ms
GC(4) User=0.11s Sys=0.02s Real=0.03s
   -- Abortable Preclean phase, Concurrent
GC(4) Pause Remark
GC(4) YG occupancy: 7371 K (20480 K)
GC(4) checkpointRootsFinalWork
GC(4) eden 0x00000000fa600000-0x00000000fa731f70-0x0000...
GC(4) _eden_chunk_index=2, _eden_chunk_capacity=1281
GC(4) _eden_chunk_array[0]=0x00000000fa700010
GC(4) _eden_chunk_array[1]=0x00000000fa731f70
GC(4) survivor 0x00000000fba00000-0x00000000fc001080-0x0000...
GC(4) _survivor_chunk_index=0, _survivor_chunk_capacity=5120
GC(4) Rescan (parallel)
GC(4) oops_do_marking_prologue
GC(4) WorkerManager::add_workers() : created_workers: 6
GC(4) GC Thread: using 6 out of 6 workers
GC(4) Finished young gen rescan work in 0th thread: 0.000 sec
GC(4) Finished young gen rescan work in 3th thread: 0.000 sec
GC(4) Finished young gen rescan work in 1th thread: 0.000 sec
GC(4) Finished young gen rescan work in 2th thread: 0.000 sec
GC(4) Finished young gen rescan work in 5th thread: 0.000 sec
GC(4) Finished remaining root rescan work in 1th thread: 0.000 sec
GC(4) Finished remaining root rescan work in 2th thread: 0.000 sec
GC(4) Finished remaining root rescan work in 0th thread: 0.000 sec
GC(4) Finished young gen rescan work in 4th thread: 0.000 sec
GC(4) Finished unhandled CLD scanning work in 0th thread: 0.000 sec
GC(4) Finished remaining root rescan work in 3th thread: 0.000 sec
GC(4) Finished remaining root rescan work in 4th thread: 0.000 sec
GC(4) Finished dirty CLD scanning work in 0th thread: 0.000 sec
GC(4) Finished remaining root rescan work in 5th thread: 0.000 sec
GC(4) Finished dirty card rescan work in 0th thread: 0.000 sec
GC(4) Finished dirty card rescan work in 2th thread: 0.000 sec
GC(4) Finished dirty card rescan work in 1th thread: 0.000 sec
GC(4) Finished dirty card rescan work in 4th thread: 0.000 sec
GC(4) Finished dirty card rescan work in 5th thread: 0.000 sec
GC(4) Finished dirty card rescan work in 3th thread: 0.000 sec
GC(4) Finished work stealing in 0th thread: 0.000 sec
GC(4) Finished work stealing in 2th thread: 0.000 sec
GC(4) Finished work stealing in 3th thread: 0.000 sec
GC(4) Finished work stealing in 1th thread: 0.000 sec
GC(4) Finished work stealing in 4th thread: 0.000 sec
GC(4) Finished work stealing in 5th thread: 0.000 sec
GC(4) WorkerManager::add_workers() : created_workers: 6
GC(4) GC Thread: using 6 out of 6 workers
...
GC(4) Pause Remark 63M->63M(80M) 1.261ms
GC(4) User=0.00s Sys=0.00s Real=0.00s
   -- Remark phase, Pause
   -- 6 threads used as specified by -XX:ParallelGCThreads=6

GC(4) Concurrent Sweep
GC(4) Concurrent Sweep 7.167ms
   -- Sweep phase, Concurrent

GC(4) User=0.02s Sys=0.00s Real=0.02s
GC(4) Old: 18246K->31462K(61440K)
   -- GC #4 (Old GC) completed

As you can see, the "-XX:ParallelGCThreads=6" option works as expected. Both "Initial Mark" and "Remark" phases used 6 threads.

Table of Contents

 About This Book

 Heap Memory Area and Size Control

 JVM Garbage Collection Logging

 Introduction of Garbage Collectors

 Serial Collector - "+XX:+UseSerialGC"

 Parallel Collector - "+XX:+UseParallelGC"

Concurrent Mark-Sweep (CMS) Collector - "+XX:+UseConcMarkSweepGC"

 What Is Concurrent Mark-Sweep (CMS) Collector

 Concurrent Mark-Sweep Collector GC Log Message Format

 Reduce Stop-The-World with Concurrent Mark and Sweep

 Parallel New (ParNew) Collector for Minor GC

 ParNew Collector - Tenuring Age Distribution

 Maximum Logging of All Phases on Young GC

 "-XX:ParallelGCThreads=6" - Young GC Parallel Threads

 "-XX:MaxTenuringThreshold=0" - Tenuring Objects Immediately

 "-XX:CMSInitiatingOccupancyFraction=20" - Initiate CMS

 Maximum Logging of All Phases on Old GC

 Maximum Logging of All Phases on Full GC

"-XX:ParallelGCThreads=6" - Old GC Parallel Threads

 "-XX:ConcGCThreads=3" - Old GC Concurrent Threads

 Garbage First (G1) Collector - "+XX:+UseG1GC"

 The Z Garbage Collector (ZGC) - "+XX:+UseZGC"

 Object References and Garbage Collection

 Garbage Collection Performance Test Program

 Performance Tests on Serial Collector

 Performance Tests on Parallel collector

 Performance Tests on Concurrent collector

 Performance Tests on G1 collector

 Garbage Collection Performance Test Summary

 References

 Full Version in PDF/EPUB