RFR: Make partial GC concurrent

Roman Kennke rkennke at redhat.com
Thu Oct 5 19:41:51 UTC 2017


It's been a long time coming, now it's finally here: concurrent partial 
GC :-)

This is almost a whole new GC. It combines our efforts to do partial GC 
with Shenandoah's concurrent evacuation and update-references goodness.

It achieves this by doing GC in 3 phases:

- init-conc-partial is the 1st STW phase. It prepares the root set, the 
collection set, etc as usual, and then scans the thread stacks etc, 
thereby evacuating all referenced cset objects and updating those GC 
roots. All evacuated oops are placed into the worker's work queue for 
later processing.

- conc-partial is a concurrent phase. It pops (or steals from other GC 
workers) oops from the work queue, scans its ref fields, and, for each 
reference to a cset object, evac the object, update the reference, and 
push the evac'd object to its work queue. When running empty, it 
attempts to steal from other workers or drain 'SATB' queue (see below).

- final-conc-partial is the finishing STW phase. It completes collection 
by draining the remaining 'SATB' queues, and processing remaining work 
queue objects as described above.

There are a few notable things to highlight:

- In order to ensure only to-space refs remain in fields, we need to 
ensure to write only to-space refs in putfield and aastore and similar 
instructions. During conc-mark it is sufficient to do a read-barrier for 
store-values. However, because evacuation and update-refs happen during 
the same concurrent phase, we now need to employ a write barrier for 
store-values.

- We also need to do the usual read- and write-barriers on target 
objects for stores and loads.

- acmp barriers and similar stuff is unaffected

- Whenever a Java thread evacuates an object, it basically means it 
steals it from GC workers processing (e.g. pushing to work queue, etc). 
To mitigate this, we push Java-thread-evacuated objects on the SATB 
queues. (It really is *not* SATB, we treat it as a simple oop buffer and 
abuse it for our purposes.) GC threads will regularily drain SATB 
buffers by simply copying the oops onto their work queues, and then work 
from there.

- Because we're treating store values with a write-barrier, and since 
evac'd objects are pushed to oop-('SATB'-)queues for later processing by 
GC threads, this essentially becomes an incremental-update-like GC 
algorithm. I.e. instead of ensuring that we traverse the old values, we 
ensure to traverse the new values. This means: 1. we don't need the SATB 
pre-barrier 2. we do need to scan + collect objects in thread stacks etc 
again during the final-conc-partial phase.

I probably forgot a ton of explanations. Please ask if anything is not 
clear.

Long story short, here's the patch:

http://cr.openjdk.java.net/~rkennke/concpartial/webrev.00/ 
<http://cr.openjdk.java.net/%7Erkennke/concpartial/webrev.00/>

I tested this by running hotspot_gc_shenandoah on x86 and aarch64, and 
also ran specjvm with fastdebug, verification, and generational 
heuristics. no crashes here. Throughput performance looks okish from 
afar, pauses are great. Obviously needs more testing and fine-tuning.




More information about the shenandoah-dev mailing list