RFR: 8254315: Shenandoah: Concurrent weak reference processing [v7]
Roman Kennke
rkennke at openjdk.java.net
Mon Oct 12 12:34:25 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. Testing: hotspot_gc_shenadoah
> (release+fastdebug, x86+aarch64), specjvm+specjbb without regressions
Roman Kennke has updated the pull request incrementally with one additional commit since the last revision:
Don't mark through a Reference that's already been discovered
-------------
Changes:
- all: https://git.openjdk.java.net/jdk/pull/505/files
- new: https://git.openjdk.java.net/jdk/pull/505/files/070fd836..34ca4991
Webrevs:
- full: https://webrevs.openjdk.java.net/?repo=jdk&pr=505&range=06
- incr: https://webrevs.openjdk.java.net/?repo=jdk&pr=505&range=05-06
Stats: 15 lines in 1 file changed: 7 ins; 7 del; 1 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