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