JEP 132: More-prompt finalization
Rezaei, Mohammad A.
Mohammad.Rezaei at gs.com
Mon Jun 1 15:03:49 UTC 2015
I read the code in the prototype and I liked what I saw (even excited!), which is the reason I spoke up.
On the API side, I was mulling over what the addition of bulk methods and even just a size() method could do to help and it struck me: the JDK has come a long way since 1.0 and there are now fully fledged, well thought out queue implementations. Is there a reason ReferenceQueue can't be upgraded to be one of those (api and/or implementation wise)?
I hope given all the reasoning that's gone into the canonical queue implementations there wouldn't be a lot of reason to debate their usefulness. But just as an example, let's consider having access to a fast, roughly accurate ReferenceQueue.size() method for the hash structures use case. A hash structure has to find the freed instances and remove them. If size() returns a large portion of the total entries, it would be better to re-hash the structure and bulk clear the references instead.
Unfortunately, I don't have a great benchmark, so I can't run the prototype quickly. I'll have to put some time aside to figure out a good way to represent the situation before I can come back with meaningful numbers.
From: Peter Levart [mailto:peter.levart at gmail.com]
Sent: Monday, June 01, 2015 5:04 AM
To: Rezaei, Mohammad A. [Tech]
Cc: 'hotspot-gc-dev at openjdk.java.net openjdk.java.net'; 'core-libs-dev at openjdk.java.net'
Subject: Re: JEP 132: More-prompt finalization
On 06/01/2015 04:42 AM, Rezaei, Mohammad A. wrote:
The problems start with the ReferenceQueue object and the heavy synchronization in it. Consider structures like j.u.WeakHashMap that need to expunge entries. If such structures are made somewhat concurrent, the lock in ReferenceQueue starts to become a serious problem:
- In structures that are concurrent at the entry level (like jdk 8's ConcurrentHashMap), if methods like get() or put() try to expunge, the lock in ReferenceQueue renders the structures non-concurrent.
The presented prototype changes the implementation of ReferenceQueue. It doesn't use a lock any more for enqueu-ing when there are no waiters and never for poll-ing. ReferenceQueue.poll() is a single volatile read when queue is empty and a read followed by CAS when it is not (with retries when contended). If there is a desire and new API could be extended, the method like the following:
Iterator<Reference<? extends T>> pollChunk(int maxChunkSize);
...could return a chunk of enqueued references (or an empty iterator) so that the reduced number of CAS instructions per de-queued reference could be traded for the greater probability of retries because of contention.
- In structures that are multi-reader-single-writer locked, read methods cannot expunge (because they have to promote to a writer), but they can't even check the queue, because that turns the multi-reader structure into a synchronized one.
By checking you mean poll() which also de-queues a reference if available? What do you do when this happens. Would you need a peek() method maybe?
- In addition to expunge calls contending on the ReferenceQueue lock, ReferenceHandler thread can also contend on the same lock.
That's right. And in the presented prototype, this is minimized by allowing ReferenceHandler thread to enqueue a chunk of pre-prepared references in one go, minimizing the need to frequently notify any possible waiters via a lock.notifyAll().
- There is no fast clear() method on ReferenceQueue. That would be quite useful on a resize event.
This would be easy to implement if new API could be added.
The above issues forced us to have a dedicated thread that does periodic expunging of References. This works ok under light load, but can fall behind under heavy load.
Because of the overhead/bottleneck of the reference processing I assume. It would be great if you could check whether the prototype in webrev.02 improves your situation. It should be simple. Just compile the sources and prepend the resulting classes to the bootclasspath of the JDK.
Can you elaborate some more on what twists were necessary or what problems you had?
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the hotspot-gc-dev