RFR: Traversal: Don't traverse new objects

Roman Kennke rkennke at redhat.com
Mon Feb 19 17:48:39 UTC 2018


Am 06.02.2018 um 21:46 schrieb Aleksey Shipilev:
> On 02/05/2018 12:16 PM, Roman Kennke wrote:
>> With Traversal GC I'm currently observing final-pauses of several dozen (e.g. ~70) ms. Turns out
>> that almost all of it is just traversing just-allocated objects. It occurs to me that this is
>> pointless work: we're not going to evacuate any new object during this cycle, and liveness
>> information may not be that useful either into next cycle because it usually degenerates quickly
>> (for new stuff). Let's not traverse new-alloc-regions, and don't count liveness there, which means
>> it's going to end up in next cycle's cset (just like the alloc-regions between cycles). This cuts
>> pauses down to 3-4ms. Yay!
>>
>> Notice that this is safe because new objects don't point to anything, and any ref stored into new
>> objects during the pause get picked up by the enqueing barrier for I-U.
>>
>> Notice that we *do* need to traverse and account evac-regions, because they have references pointing
>> to interesting stuff. Hence the disctinction for is_alloc_region() (better ideas welcome!).
>>
>> Also notice that this opens up an interesting opportunity for optimizing the enqueue-barrier: we
>> could now elide ENQBs on objects known to be new. (In addition to known-NULL, which we already
>> check, and already-enqueued, which we don't do yet. We could also do pretty much what we do with WBs
>> and RBs and hoist them out of loops, etc. Lots of work to do there, and opportunities for
>> improvements).
>>
>> http://cr.openjdk.java.net/~rkennke/traversal-no-traverse-new/webrev.00/
>
> I need more time to understand the logic of this patch. It is seriously weird to see next-TAMS setup
> in ShenandoahFreeSet::try_allocate_in, which is on generic allocation path which also should work
> for non-Traversal GC modes.

I guarded the new parts with appropriate if
(conc_traversal_in_progress()) checks..

> The patch fails at least AllocHumongousFragment with:
>   #  assert(!_heap->is_marked_next(oop(humongous_obj))) failed: must not be marked

This one is caused by humongous regions not getting flagged as
alloc_regions during allocation. Fixed in the new changeset.

> Other comments:
>
> *) So wait, this means alloc-regions are not the candidates for immediate reclamation now?
>
>   546         if (r->is_humongous_start() && !r->has_live() && !r->is_alloc_region()) {

Yes, exactly.

> *) Same for regular trashing?
>
>   556         } else if (!r->is_empty() && !r->has_live() && !r->is_alloc_region()) {

Yep.

> *) Excess parentheses:
>
> shenandoahTraversalGC.cpp:
>    73       if ((!_heap->is_marked_next(obj)) && _heap->mark_next(obj)) {
>
> shenandoahTraversalGC.inline.hpp:
>    54     if ((!_heap->is_marked_next(obj)) && _heap->mark_next(obj)) {
>

Fixed.

> *) Comment is obsolete.
>
>   981           _verify_liveness_disable,    // liveness data must be complete here

Fixed.

Differential:
http://cr.openjdk.java.net/~rkennke/traversal-no-traverse-new/webrev.01.diff
Full-patch:
http://cr.openjdk.java.net/~rkennke/traversal-no-traverse-new/webrev.01/

Passes all hotspot_gc_shenandoah tests

Roman


More information about the shenandoah-dev mailing list