RFR: Mixed evacuation [v2]

Roman Kennke rkennke at openjdk.java.net
Mon Apr 12 20:58:16 UTC 2021


On Thu, 8 Apr 2021 15:32:13 GMT, Kelvin Nilsen <kdnilsen at openjdk.org> wrote:

>> This code adds to generational Shenandoah the ability to perform concurrent garbage collection of young-gen and old-gen memory. Following completion of an old-gen concurrent marking effort, we select certain old-gen heap regions to serve as candidates for future collection sets. All dead objects within the old-gen heap regions that are not part of this candidate set are coalesced and filled so that remembered-set scanning of these old-gen heap regions will not be confused by "zombie objects" (objects that old-gen has decided are dead, which reside in regions that have not yet been collected). After concurrently coalescing and filling these dead objects, each subsequent young-gen evacuation pass includes a subset of the old-gen candidates until all candidates have been collected. This code passes TIER1 and hotspot-gc-shenandoah jtreg tests without regressions. A new jtreg test has been added to exercise concurrent old/young GC.
>
> Kelvin Nilsen has updated the pull request incrementally with one additional commit since the last revision:
> 
>   Chasing bug during prepare_for_old_collection
>   
>   One bug fix, a few cosmetic improvements, a change in loop structure to possibly avoid a gcc
>   optimization error.

Nice progress!
First-pass review follows.

Please, check out jcheck complaints under the 'Checks' tab and fix them. I'll start a review in the meantime.

src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp line 92:

> 90:     prepare_for_old_collections();
> 91:   } else {
> 92:     ShenandoahHeap* heap = ShenandoahHeap::heap();

I'd factor out the whole else block here to call prepare_for_young_collection() or whatever is fitting there.

src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp line 440:

> 438:   return (_generation->generation_mode() == GLOBAL)
> 439:     || (_generation->generation_mode() == YOUNG && region->affiliation() == YOUNG_GENERATION)
> 440:     || (_generation->generation_mode() == OLD && region->affiliation() == OLD_GENERATION);

I wouldn't change indentation here, or if it needs changing, then line up the || with the _generation above. Iow, shift it 4 spaces to the right instead of 2 spaces to the left.

src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp line 454:

> 452:   for (size_t i = 0; i < num_regions; i++) {
> 453:     ShenandoahHeapRegion* region = heap->get_region(i);
> 454:     if (!in_generation(region))

Please always use { and } in if (and else) constructs.

src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp line 475:

> 473: 
> 474:   // This loop is written as while rather than for because of
> 475:   // suspected gcc error in translating/optimizing for-loop

WTF, really? Do we have any indication of this?

src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp line 515:

> 513:   // evacuated.  In the future, this threshold percentage may be specified on
> 514:   // the command line or preferrably determined by dynamic heuristics.
> 515: #define CollectionThresholdGarbagePercent 50

We already have ShenandoahGarbageThreshold (defaults to 60 iirc) maybe we want to use this? Or use separate global/old/young thresholds?

src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.hpp line 80:

> 78: // For expediency, we'll have a single class that is a "union" of
> 79: // necessary functionality.
> 80: 

Hmmhmm, this seems a suboptimal design. My intuition would have been to not have each heuristic need to know about any old heuristic, but keep them separate, and compose functionality elsewhere, but I leave that to you. The way it looks now it may end up recursive (young-heuristics->old-heuristics->old-heuristics->...-> etc)

src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp line 518:

> 516:   // precisely where the regulator is allowed to cancel a GC.
> 517:   ShenandoahOldGC gc(generation, _allow_old_preemption);
> 518: 

Lone whitespace change here.

src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp line 129:

> 127: void ShenandoahGeneration::prepare_gc() {
> 128:   reset_mark_bitmap();
> 129: 

Lone whitespace change here.

test/hotspot/jtreg/gc/shenandoah/generational/TestConcurrentEvac.java line 35:

> 33:  *  of old-gen GC passes is very simplistic.  A further shortcoming of the
> 34:  *  Generational Shenandoah as of introduction of this test is that it does
> 35:  *  currently support full GC.  If garbage collection falls behind mutator

You probably meant to say that it "does currently *not* support full GC"

-------------

Changes requested by rkennke (Reviewer).

PR: https://git.openjdk.java.net/shenandoah/pull/29


More information about the shenandoah-dev mailing list