JDK-8204612 : Make dynamic parallelization of reference processing work default in G1
  • Type: CSR
  • Component: hotspot
  • Sub-Component: gc
  • Priority: P4
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 11
  • Submitted: 2018-06-08
  • Updated: 2018-06-18
  • Resolved: 2018-06-18
Related Reports
CSR :  
Description
Summary
-------

Processing of j.l.ref.References in the G1 garbage collection pauses should be parallel by default and dynamically adapt the number of threads based on available work.

Problem
-------

Users currently need to manually turn on parallel processing for java.lang.ref.References during a G1 gc pause. This is an all-or-nothing setting: when turned on, G1 uses all available threads (as set by -XX:ParallelGCThreads) for this phase, that itself consists of several subphases, independent of available work. This means that often when in a particular garbage collection, or in a particular subphase of java.lang.ref.Reference processing there is not a lot of work to do, G1 still needs to start up and synchronize all threads for shutdown.
Starting up and synchronizing threads for shutdown immediately afterwards can take a relatively long amount of time due to interaction with the operating system.
So a user can select between potentially a slow java.lang.ref.Reference processing phase if there is lots of work to do, or performance losses due to java.lang.ref.Reference processing when there is not a lot of work to do.

Solution
--------

For G1 we will by default enable parallel java.lang.ref.Reference processing and use the existing mechanism where G1 tries to select a more optimal number of threads based on heuristics the amount of work per sub-phase of java.lang.ref.Reference processing.

Specification
-------------

For the G1 collector, the default value for the ParallelRefProcEnabled option will be true if more than one thread is used and not otherwise overridden. I.e.

    --- old/src/hotspot/share/gc/g1/g1Arguments.cpp	2018-06-08 15:53:28.148957195 +0200
    +++ new/src/hotspot/share/gc/g1/g1Arguments.cpp	2018-06-08 15:53:27.788945904 +0200
    @@ -122,6 +122,10 @@
         FLAG_SET_DEFAULT(GCPauseIntervalMillis, MaxGCPauseMillis + 1);
       }
       
    +  if (FLAG_IS_DEFAULT(ParallelRefProcEnabled) && ParallelGCThreads > 1) {
    +    FLAG_SET_DEFAULT(ParallelRefProcEnabled, true);
    +  }
    +
       log_trace(gc)("MarkStackSize: %uk  MarkStackSizeMax: %uk", (unsigned int) (MarkStackSize / K), (uint) (MarkStackSizeMax / K));

The mechanism to select the number of parallel threads uses the existing flag ReferencesPerThread that determines the number of threads to be used for this phase: for every ReferencesPerThread java.lang.ref.References to work on, add another thread up to the current maximum as determined elsewhere.

To reiterate, only G1 observes ReferencesPerThread at this time. So using -XX:+ParallelRefProcEnabled with other collectors behaves the same as before, i.e. all currently available threads are used for parallel reference processing.

Comments
Moving to Approved.
18-06-2018