Java 8 GC Tutorials - Herong's Tutorial Examples - v1.03, by Dr. Herong Yang
"-XX:ParallelGCThreads=n" - # of Threads
This section describes how to use the '-XX:ParallelGCThreads=n' JVM option to control the number threads to be used by the Parallel Collector.
In the previous tutorial, we learned that the Parallel collector did use 4 parallel threads to perform both minor and major GCs.
The next question is then how the Parallel collector determines the number of threads to use and any options to control it.
By search Java documentation, I found this description: "On a machine with N hardware threads where N is greater than 8, the parallel collector uses a fixed fraction of N as the number of garbage collector threads. The fraction is approximately 5/8 for large values of N. At values of N below 8, the number used is N. On selected platforms, the fraction drops to 5/16.
The output from the previous tutorial did confirm what's said in Java documentation. The Parallel collector used 4 parallel threads, because my Windows computer has 2 cores and 4 logical processors.
To control the number of parallel treads explicitly, we can use the "-XX:ParallelGCThreads=n" JVM option. In the example below, we are running our test program with 2 parallel threads:
herong> \progra~1\java\jdk1.8.0\bin\java -Xms2m -Xmx64m -XX:+UseParallelGC \ -XX:+PrintGCDetails -XX:+PrintGCTimeStamps \ -XX:-XX:ParallelGCThreads=2 -XX:+PrintGCTaskTimeStamps \ GarbageCollection > output.txt (Ctrl-C) herong> more output.txt Step/TotalMemory/FreeMemory/UsedMemory: 0.768: [GC (Allocation Failure) [PSYoungGen: 511K->248K(768K)] 1280K->1176K(1792K), 0.0020402 secs] [Times: user=0.00 sys=0.03, real=0.02 secs] VM-Thread 1801012 1805624 1806301 GC-Thread 0 entries: 13 [ old-to-young-roots-task 1801893 1801928 ] [ scavenge-roots-task 1801932 1802032 ] [ thread-roots-task 1802034 1802044 ] [ thread-roots-task 1802045 1802054 ] [ thread-roots-task 1802055 1802058 ] [ thread-roots-task 1802059 1802683 ] [ thread-roots-task 1802684 1802687 ] [ scavenge-roots-task 1802688 1802693 ] [ scavenge-roots-task 1802694 1802697 ] [ scavenge-roots-task 1802698 1802702 ] [ scavenge-roots-task 1802702 1802716 ] [ scavenge-roots-task 1802717 1805389 ] [ steal-task 1805390 1805579 ] GC-Thread 1 entries: 9 [ old-to-young-roots-task 1801918 1801946 ] [ scavenge-roots-task 1801949 1802049 ] [ thread-roots-task 1802052 1802061 ] [ thread-roots-task 1802062 1802462 ] [ thread-roots-task 1802463 1802946 ] [ scavenge-roots-task 1802947 1802950 ] [ scavenge-roots-task 1802951 1802952 ] [ steal-task 1802952 1805547 ] [ waitfor-barrier-task 1805548 1805615 ] 0.771: [Full GC (Ergonomics) [PSYoungGen: 248K->246K(768K)] [ParOldGen: 928K->921K(1792K)] 1176K->1168K(2560K), [Metaspace: 1555K->1555K(4480K)], 0.0050992 secs]
VM-Thread 1807541 1812770 1819510 GC-Thread 0 entries: 16 [ noop task 1807518 1807528 ] [ mark-from-roots-task 1807603 1807983 ] [ thread-roots-marking-task 1807984 1808006 ] [ thread-roots-marking-task 1808006 1808522 ] [ thread-roots-marking-task 1808523 1808525 ] [ mark-from-roots-task 1808526 1808529 ] [ mark-from-roots-task 1808529 1808532 ] [ mark-from-roots-task 1808532 1808535 ] [ mark-from-roots-task 1808535 1808571 ] [ mark-from-roots-task 1808571 1808572 ] [ mark-from-roots-task 1808572 1808574 ] [ mark-from-roots-task 1808574 1808575 ] [ steal-marking-task 1808575 1809423 ] [ drain-region-task 1814309 1817604 ] [ steal-region-task 1817605 1817608 ] [ waitfor-barrier-task 1817608 1818582 ] GC-Thread 1 entries: 14 [ noop task 1807503 1807504 ] [ mark-from-roots-task 1807746 1807764 ] [ thread-roots-marking-task 1807765 1807771 ] [ thread-roots-marking-task 1807772 1807777 ] [ thread-roots-marking-task 1807777 1807778 ] [ thread-roots-marking-task 1807779 1807780 ] [ thread-roots-marking-task 1807780 1809401 ] [ steal-marking-task 1809402 1809405 ] [ waitfor-barrier-task 1809405 1809452 ] [ drain-region-task 1812810 1816131 ] [ update-dense_prefix-task 1816134 1816156 ] [ update-dense_prefix-task 1816157 1816161 ] [ update-dense_prefix-task 1816161 1816164 ] [ steal-region-task 1816165 1818377 ] ...
From the output, I can see that the Parallel Collector did use 2 multiple threads to perform the first Minor GC and the first Major GC as we specified.
Table of Contents
Heap Memory Area and Size Control
JVM Garbage Collection Logging
Introduction of Garbage Collectors
Serial Collector - "+XX:+UseSerialGC"
►Parallel Collector - "+XX:+UseParallelGC"
Parallel Collector GC Log Message Format
"-XX:+PrintGCTaskTimeStamps" - Print GC Threads
►"-XX:ParallelGCThreads=n" - # of Threads
Parallel Collector Stops Application for Minor/Major GC
PSYoungGen Collector Using Tenuring Age
Parallel Collector Changing NewRatio and SurvivorRatio
Parallel Collector Adaptive Size Policy
Adaptive Size Policy Log Messages
"-XX:+PrintAdaptiveSizePolicy" - Minor GC Report
Adaptive Size Policy Changed Survivor Space
Adaptive Size Policy Changed Eden Space
Adaptive Size Policy for Best Latency
Adaptive Size Policy for Best Throughput
Concurrent Mark-Sweep (CMS) Collector - "+XX:+UseConcMarkSweepGC"
Garbage First (G1) Collector - "+XX:+UseG1GC"
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