RFR: 8254315: Shenandoah: Concurrent weak reference processing [v5]

Roman Kennke rkennke at openjdk.java.net
Sat Oct 10 21:27:19 UTC 2020


> Until now, references (as in java.lang.ref.Reference and its subclasses WeakReference, SoftReference, PhantomReference
> and the non-public FinalReference - I'll collectively call them weak references for the purpose of clarity). Workloads
> that make heavvy use of such weak references will therefore potentially cause significant GC pauses.  There are 3 main
> items that contribute to pause time linear to number of references, or worse:
> - We need to scan and consider each reference on the various 'discovered' lists.
> - We need to mark through subgraph of objects that are reachable only through FinalReference. Notice that this is
>   theoretically only bounded by the live data set size.
> - Finally, all no-longer-reachable references need to be enqueued in the 'pending list'
> 
> The problem is somewhat mitigated by pre-cleaning the discovered list: Any weak reference that we find to be strongly
> reachable will be removed before we go into the final-mark-pause. However, that is only a band-aid.
> The solution to this is two-fold:
> 1. Extend concurrent marking to also mark the 'finalizable' subgraph of the heap. This requires to extend the marking
> bitmap to allow for two kinds of reachability: each object can now be strongly and finalizably reachable. Whenever
> marking encounters a FinalReference, it will mark through the referent and switch to 'finalizably' reachability for all
> objects starting from the referent. When marking encounters finalizably reachable objects while marking strongly, it
> will 'upgrade' reachability of such objects to strongly reachable. All of this can be done concurrently. Any encounter
> of a Reference (or subclass) object will enqueue that object into a thread-local 'discovered' list. Except for
> FinalReference, marking stops there, and does not mark through the referent. 2. Concurrent processing is performed
> after the final-mark pause. GC workers scan all discovered lists that have been collected by concurrent marking, and
> depending on reachability of the referent, either drop the Reference, or enqueue it into the global 'pending' list
> (from where it will be processed by Java reference handler thread). In addition to that, we must ensure that no
> referents become resurrected by accessing Reference.get() on it. In order to achieve this, we employ special barriers
> in Reference.get() intrinsics that return NULL when the referent is not reachable.

Roman Kennke has updated the pull request with a new target base due to a merge or a rebase. The pull request now
contains 41 commits:

 - Merge remote-tracking branch 'upstream/master' into shenandoah-concurrent-weakrefs
 - Prevent double-discovery of references
 - Also abandon pending list when abandoning discovered lists
 - Implement reference-processing statistics
 - Implement abandoning partial discovery. Remove unused methods.
 - Remove leftovers of precleaning
 - Remove unused is_access_on_jlr_reference() helper method
 - Invert weak/native condition in interpreter native-LRB for clarity
 - Merge remote-tracking branch 'upstream/master' into shenandoah-concurrent-weakrefs
 - Use existing idiom for checking for intanceRefKlass, instead of introducing new code
 - ... and 31 more: https://git.openjdk.java.net/jdk/compare/cc52358c...da242318

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

Changes: https://git.openjdk.java.net/jdk/pull/505/files
 Webrev: https://webrevs.openjdk.java.net/?repo=jdk&pr=505&range=04
  Stats: 2429 lines in 54 files changed: 1654 ins; 602 del; 173 mod
  Patch: https://git.openjdk.java.net/jdk/pull/505.diff
  Fetch: git fetch https://git.openjdk.java.net/jdk pull/505/head:pull/505

PR: https://git.openjdk.java.net/jdk/pull/505


More information about the shenandoah-dev mailing list