RFC: Adding generational support to ShenandoahHeapRegion

Roman Kennke rkennke at redhat.com
Mon Aug 17 20:53:03 UTC 2020


Hi Kelvin,

Let me reply to your points inline :-)



> 1. Adding generational GC to Shenandoah is not necessarily our vision
> of the complete end-all best solution for all situations.  It is our
> attempt to deliver incremental improvement with "limited" effort and
> a near-term planning horizon.

Fair enough. :-)

> 2. I understand your perspective that using Shenandoah for young-gen
> collection rather than old-gen collection is not what you would have
> recommended.  Here are some of the reasons we are exploring this
> choice:
> 
>     a) Many of our important customers have very large young-gens,
> gigabytes and larger for just young-gen.  For this reason, we do not
> want to do stop-the-world young-gen.

I agree!

>     b) Integrating two relocating concurrent GC (for both old- and
> young-gen) is perceived as overly complex for current needs

I agree too!

>     c) It is very important for allocation to use efficient TLABs,
> which depends on defragmentation/compaction, which Shenandoah does
> well.  Evacuation GC is most efficient when a high-percentage of heap
> is garbage.  This is generally true for young-gen memory.

Yup, agree again!

>     d) Our experimentation with Shenandoah is that it does not
> perform as well when the heap is highly utilized (in fact, Shenandoah
> seems to perform best when less than 30% of heap is live).

That is because marking (especially through 'static' old-space stuff)
takes too long and eats up CPU resources, is that right?

>     e) Stable, highly utilized, long-term memory, derives less
> benefit from repeated defragmentation copying.  In general, we plan
> to use concurrent mark and sweep for old-gen memory.

I don't really agree with that conclusion ;-)

>     f)  Our planned region-based approach to old-gen memory allows
> the old-gen collector to identify certain regions as ready to benefit
> from defragmentation.  When this is detected, the old-gen collector
> will re-introduce the region to Shenandoah, with all objects already
> tagged as having max age.  Shenandoah will evacuate the live objects
> from this region, immediately promoting them back into more
> efficiently packed regions of old-gen memory.

My idea to solve the problem of having to coordinate 2 relocating
collectors is to not do that, but instead take advantage of the fact
that all collections are concurrent anyway, and so it doesn't matter
all that much if we piggy-back some extra-work on a normal young-gen
cycle and defragment one or more old-gen regions too - depending on
some heuristic, so that it eventually defragments old-gen regularily.
(Failing that, we'd run a full-concurrent Shenandoah cycle over all of
the heap.) This requires card-marking to also track old->old and young-
>old references, though. It's basically G1's mixed collections, but
fully concurrent. (Or, put differently, kinda what you suggested with
adding-back old regions to young-gen so that it gets defragmented.) The
advantage is that old- and young- collections do not interleave and
thus don't require extra coordination.

WDYT?

Roman

> 3. Thanks for your suggestion for quick determination of object-in-
> cset.  We probably will want to do something like that.


> 
> 
> On 8/17/20, 5:42 AM, "Roman Kennke" <rkennke at redhat.com> wrote:
> 
>     CAUTION: This email originated from outside of the organization.
> Do not click links or open attachments unless you can confirm the
> sender and know the content is safe.
> 
> 
> 
>     Hi Kelvin,
> 
>     the change itself seems relatively uncontroversial as it is.
> 
>     I have sent you my w-i-p a while ago, which also covers this
> suggested
>     change, and much more (tracking age, promoting objects,
> dynamically
>     allocating regions for old-gen, etc), have you considered it?
> 
>     http://cr.openjdk.java.net/~rkennke/generation.patch
> 
> 
>     I am not quite sure how it makes sense to use Shenandoah
> 'primarily for
>     young gen collection'. Intuitively I'd use Shenandoah for both
> old and
>     young gen, or even just for old-gen and a STW scavenger for
> young-gen.
> 
>     Regarding point #4, it may at some point be worth to use a
> similar
>     mechanism like we use to quickly determine object-in-cset, i.e. a
>     biased lookup-table. That's more efficient than finding a region,
> and
>     then looking up the field there. But that is certainly an
> optimization
>     for later.
> 
>     Thanks for your work on this!
> 
>     Cheers,
>     Roman
> 
>     On Fri, 2020-08-14 at 00:34 +0000, Nilsen, Kelvin wrote:
>     > This webrev details a suggested change to the definition of
>     > ShenandoahHeapRegion for the purpose of enabling multi-
> generational
>     > garbage collection:
>     >
>     >     
> http://cr.openjdk.java.net/~kdnilsen/two-generations/webrev.00/
>     > 
>     > Here is some background on how we anticipate this facility will
> be
>     > used:
>     >
>     >   1. Our thoughts are to use Shenandoah as currently
> implemented
>     > primarily for young-gen collection, so the default constructor
> shows
>     > that all heap regions are allocated as belonging to the young
>     > generation.
>     >
>     >   2. Eventually, we will set aside certain heap regions to
> represent
>     > old-generation memory.  As objects are tenured, the Shenandoah
>     > collector evacuates these objects out of a young-gen HeapRegion
> into
>     > an old-generation heap region.
>     >
>     >   3. Certain existing operations of the existing Shenandoah
> collector
>     > (marking, for example) need to efficiently determine whether
>     > particular objects referenced by pointers reside in young-gen
> memory
>     > or old-gen memory.   Shenandoah GC will give non-traditional
>     > treatment to any pointers residing outside the young-
> generation.
>     >
>     >   4. We intend to use the heap->heap_region_containing(address)
>     > service to find the heap region that corresponds to a
> particular
>     > object address and then consult the value of the _gen field to
>     > determine whether a particular object resides in old-gen or
> new-gen
>     > memory.
>     >
>     >   5. Fast-path mutator operations do not need to know which
>     > generation holds particular objects.  The most common
> requirement is
>     > for a background GC thread to be processing pointers within a
> tight
>     > loop.  In this common use case, we expect that the loop-
> invariant
>     > variables RegionSizeBytesShift, _base, and _regions would all
> reside
>     > in registers and their content would be loaded within the
> loop's pre-
>     > header.
>     >
>     > I welcome discussion and recommendations for improvement.
>     >
>     > (We are doing prototype development off trunk.  We would not
> expect
>     > to merge any of this code until it is all working and
> performance
>     > benefits are demonstrated.)
>     >
>     >
>     >
>     >
>     >
> 
> 



More information about the shenandoah-dev mailing list