RFR (M) 8150393: Maintain the set of survivor regions in an array between GCs

Thomas Schatzl thomas.schatzl at oracle.com
Mon May 2 12:40:20 UTC 2016


Hi Mikael,

On Mon, 2016-05-02 at 13:19 +0200, Mikael Gerdin wrote:
> Hi,
> 
> On 2016-04-28 17:50, Thomas Schatzl wrote:
> > 
> > Hi Mikael,
> > 
> > On Thu, 2016-04-28 at 12:59 +0200, Mikael Gerdin wrote:
> > > 
> > > Hi,
> > > 
> > > Please review this refactoring of the G1 YoungList class to
> > > simplify
> > > the
> > > management of young regions.
> > > 
> > > Survivor regions are tracked in a sublist of the YoungList linked
> > > list
> > > (using HeapRegion::_next_young_region) with explicit tracking of
> > > the
> > > head and tail of the survivor regions.
> > > The number of survivors is tracked in a special counter in
> > > YoungList
> > > and
> > > at the end of a GC the amazingly named
> > > YoungList::reset_auxillary_lists
> > > makes the survivor regions proper members of the YoungList.
> > > 
> > > My suggested fix is to explicitly track survivors in a
> > > GrowableArray
> > > instead to make way for the complete removal of
> > > HeapRegion::_next_young_region. There is a lot of overlap between
> > > the
> > > incremental collection set and the young list and the only case
> > > where
> > > they are not representing the exact same set of regions is during
> > > a
> > > GC,
> > > where the "to-space" survivor regions need explicit tracking.
> > > 
> > > By tracking the survivor regions in an array instead of a linked
> > > list
> > > we
> > > can also speed up concurrent root region scanning by getting rid
> > > of
> > > mutex synchronization when iterating over the survivor regions to
> > > scan.
> > > 
> > > In order to maintain the integrity of the YoungList linked list
> > > I've
> > > modified the code to append the survivors to that list in
> > > reset_auxillary_lists for now, but I plan to change that in an
> > > upcoming
> > > change.
> > > 
> > > Webrev of complete change:
> > > http://cr.openjdk.java.net/~mgerdin/8150393/webrev.0.full/
> > > Webrev of survivor array creation:
> > > http://cr.openjdk.java.net/~mgerdin/8150393/webrev.0.survarray/
> > > Webrev of cleanup of survivor linked list uses
> > > http://cr.openjdk.java.net/~mgerdin/8150393/webrev.0.cleanup/
> > > 
> > > 
> > > Bug: https://bugs.openjdk.java.net/browse/JDK-8150393
> > > Testing: GC RBT Testing, Performance testing shows no significant
> > > regressions
> >    - could you make the _claimed_survivor_index a size_t because it
> > can
> > never ever get negative because it's never decremented.
> Since it's used together with a GrowableArray I'd just be forced to 
> perform a bunch of casts if I made it a size_t so I'd prefer to keep
> it an int. Hopefully someday we'll create a sane array class.

Okay :)

> >    - I find the "1-based index" comments quite confusing, but
> > that's
> > probably just me. Lots of other code does the same without any
> > further
> > commenting on that. I am also not sure how this "avoids signed
> > overflow" issues.

There is still one of those in g1ConcurrentMark.hpp. Care to improve
the "1-based" first word there too?

I do not need a re-review for this.

> >    - instaed of
> > 
> >   293   int claimed_index = Atomic::add(1,
> > &_claimed_survivor_index);
> >   294   assert(claimed_index > 0, "%d must always be positive",
> > claimed_index);
> >   295   claimed_index--;
> > 
> > I would kind of prefer
> > 
> > int claimed_index = Atomic::add(1, &_claimed_survivor_index) - 1;
> > 
> > which is more concise, and the assert quite confusing as
> > Atomic::add guarantees the addition anyway. Since the resulting
> > value is at least always 0 (even more obvious if you make that
> > variable a size_t), I do not see a need for these three lines.
> diff --git a/src/share/vm/gc/g1/g1ConcurrentMark.cpp 
> b/src/share/vm/gc/g1/g1ConcurrentMark.cpp
> --- a/src/share/vm/gc/g1/g1ConcurrentMark.cpp
> +++ b/src/share/vm/gc/g1/g1ConcurrentMark.cpp
> @@ -288,11 +288,7 @@
>     // Currently, only survivors can be root regions.
>     const GrowableArray<HeapRegion*>* survivor_regions = 
> _young_list->survivor_regions();
> 
> -  // The claimed survivor index is a 1-based index into the
> survivor 
> regions array
> -  // this allows us to initialize the index to 0 and avoid signed 
> overflow issues.
> -  int claimed_index = Atomic::add(1, &_claimed_survivor_index);
> -  assert(claimed_index > 0, "%d must always be positive",
> claimed_index);
> -  claimed_index--;
> +  int claimed_index = Atomic::add(1, &_claimed_survivor_index) - 1;
>     if (claimed_index < survivor_regions->length()) {
>       return survivor_regions->at(claimed_index);
>     }
> 

Looks good.

> > 
> > 
> >    - this is just personal preference (and I do not know what's
> > better),
> > I tend to put the region indices into such arrays instead of the
> > pointers. Region indices are always 4 bytes, which is negligible I
> > guess here.
> > 
> >    - pre-existing, and just a note to create a CR:
> > maybe G1ConcurrentMark::scan_root_regions() can be simplified with
> > the
> > recent addition of the run_task() with the # of threads method.
> > 
> > Also, that number of threads should also be capped by the number of
> > available survivor regions (may be interesting on large systems
> > with >100 marking threads...)
> > 

Done, see the other rfr.

Thanks,
  Thomas



More information about the hotspot-gc-dev mailing list