RFR: Refactor allocation failure and explicit GC handling

Zhengyu Gu zgu at redhat.com
Wed Jan 17 02:45:24 UTC 2018


ShenandoahConcurrentThread::handle_alloc_failure() now takes monitor 
lock, and this method is in ShenandoahHeap::allocate_memory() path, in 
turn, can be called inside write barrier ... seems to be the scenario we 
talked before, that we *can not* do.

Maybe, I missed something?

Thanks,

-Zhengyu

On 01/16/2018 04:36 PM, Aleksey Shipilev wrote:
> http://cr.openjdk.java.net/~shade/shenandoah/refactor-af-explicit-gc/webrev.01/
> 
> This refactors the allocation failure and explicit GC handling, and prepares the code for the
> arrival of STW Degenerate GC.
> 
> Tour of changes:
> 
> 1. For historical reasons, we used to have the full_gc_* members in ShConcThread to handle the
> allocation failure, because that was the only option available for us. With the advent of degenerate
> CM and UR it started to mean just the "allocation failure". With Degenerate GC, it would further
> depart from its original meaning. So, renaming full_gc_* to alloc_failure_* to capture the real
> intent and rewiring accordingly is one part of the refactoring.
> 
> Behavioral change: Alloc-failed threads are not immediately kicked after degenerated CM and
> degenerate UR, and instead they wait for the end of the cycle. This avoids a bad race against the
> alloc-failed threads that are coming with cancellation at the same time, and it keeps us away from
> OOM-during-evac when after-CM cleanup cannot regain enough space. This would be the behavior of the
> upcoming Degenerated GC anyway.
> 
> 
> 2. There is also the path that invokes explicit GCs. Again, for historical reasons, that originally
> meant only Full GC. With the advent of ExplicitGCInvokesConcurrent support, it means both concurrent
> and Full GC cycles! So, renaming conc_gc_* to explicit_gc_* and rewiring accordingly is the second
> part of refactoring.
> 
> Behavioral change: Explicit GC no longer cancels the concurrent cycle, instead it waits for another
> control loop iteration to start explicit GC. This is for the best, because it both simplifies our
> handling logic, and allows requesters to wait for their own cycle. This is interesting when
> concurrent cycle is running, ExplicitGCInvokesConcurrent is enabled and System.gc() is called: the
> requesting thread would wait for one complete GC cycle to start and finish.
> 
> 
> 3. The logic in main control loop used to handle weird paths from cancellations back to Full GC.
> Having proper designations for alloc failure and explicit GCs help to write out the proper
> priorities for these events. This also allows us to potentially plug Degenerate GC for the
> out-of-cycle Allocation Failures, instead of unconditionally doing the Full GC.
> 
> 
> 4. Pulling the code out of ShenandoahHeap back to ShenandoahConcurrentThread allows to reduce
> coupling. Also, ShenandoahGCCause is eliminated in favor of proper GCCause, which simplifies logic
> further.
> 
> 
> 5. Additionally, gc+stats now tells things like these:
> 
> ----- 8< ----------------------------------------------------------------------------------------
> 
>   Under allocation pressure, concurrent cycles will cancel, and either continue phase under
>   stop-the-world pause or result in stop-the-world Full GC. Increase heap size, tune GC heuristics,
>   or lower allocation rate to avoid degenerated and Full GC cycles.
> 
>     85 successful concurrent GC cycles
>     27 cancelled concurrent GC cycles (5 degenerated marks, 10 degenerated update refs, 12 Full GCs)
>     11 out-of-cycle allocation failures (11 Full GCs)
>      0 explicitly requested GC cycles (0 Full GCs)
> 
> ----- 8< ----------------------------------------------------------------------------------------
> 
> 
> Testing: hotspot_gc_shenandoah
> 
> Thanks,
> -Aleksey
> 


More information about the shenandoah-dev mailing list